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