1,嘚瑟
- 自打我用上了concurrent.futures模塊,我就深深愛上了它,真是愛不釋手(現在我每寫一些python模塊,都會考慮使用futures加快代碼的執行速度。)
- 爲啥?因爲concurrent.futures好用又簡單。
2,如何使用
-
網上也有許多資料解釋如何使用該模塊,但是確實存在很多坑,畢竟大部分都不是專家級別的,寫寫博客可能就是日常的筆記而已。。。但是,要是新手看到了,並且按照網友們寫的一步一步執行,有時候你就會跌入萬丈深淵,我就是受害者之一0.0(em…不排除我寫的一些文章也有大坑。。慚愧慚愧0.0)。
-
所以每次接觸一個新API的時候,最好先看看官網的解釋,這樣入坑的可能性會降低很多。所以python3的concurrent.futures模塊中文API鏈接如下:
https://docs.python.org/zh-cn/3/library/concurrent.futures.html
3,我習慣的用法
以下相關代碼參考子、自API,分爲異步調用和同步調用,那什麼時候用異步調用,什麼時候用同步調用呢?結合我自身的工程實踐,給出我的理解:
- 通常情況下會用異步調用,畢竟速度快,但是我認爲條件是,數據規模不是很大,而且並行任務的入隊速度和出隊速度相差不多的情況下,用異步調用很方便,速度也很快。(解決數據規模大的問題,有很多方法,其中之一是:可以將待處理的大規模數據分塊,以分批並行處理)。
- 如果待處理的數據規模超大,也沒分塊,同時並行任務的入隊速度遠高於出隊速度,那麼會出現內存不斷增加直至溢出的情況,這樣很危險的,會導致服務器崩了。。。。這時候可以考慮同步調用
- 同步調用速度相對慢很多,但是有些情況下可以解決內存溢出的問題。比如並行任務入隊操作是從本地文件讀取數據,出隊操作是對該部分數據進行特別耗時的處理,這樣就可能出現內存溢出。
3.1 異步調用
import concurrent.futures
import urllib.request
URLS = ['http://www.foxnews.com/',
'http://www.cnn.com/',
'http://europe.wsj.com/',
'http://www.bbc.co.uk/',
'http://some-made-up-domain.com/']
# Retrieve a single page and report the URL and contents
def load_url(url, timeout):
with urllib.request.urlopen(url, timeout=timeout) as conn:
return conn.read()
# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
# Start the load operations and mark each future with its URL
future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
for future in concurrent.futures.as_completed(future_to_url):
url = future_to_url[future]
try:
data = future.result()
except Exception as exc:
print('%r generated an exception: %s' % (url, exc))
else:
print('%r page is %d bytes' % (url, len(data)))
- 同步調用
利用future.result()實現同步調用,示例代碼如下:
import concurrent.futures
import urllib.request
URLS = ['http://www.foxnews.com/',
'http://www.cnn.com/',
'http://europe.wsj.com/',
'http://www.bbc.co.uk/',
'http://some-made-up-domain.com/']
# Retrieve a single page and report the URL and contents
def load_url(url, timeout):
with urllib.request.urlopen(url, timeout=timeout) as conn:
return conn.read()
# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
# Start the load operations and mark each future with its URL
for url in URLS:
re = executor.submit(load_url, url, 60).result()