python3多線程、多進程之concurrent.futures模塊

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()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章