此代码(snippet_1)改编自doc中的ThreadPoolExecutor示例
import concurrent.futures
import urllib.request
URLS = ['http://www.foxnews.com/',
'http://www.cnn.com/',
'http://europe.wsj.com/',
'http://www.bbc.co.uk/']
# 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]
print('%r page is %d bytes' % (url, len(data)))
print('after')
效果很好,并得到
' http://www.foxnews.com/ '页面为990869字节' http://www.cnn.com/ '页面为990869字节' http://www.bbc.co.uk/ '页面为990869字节' http://europe.wsj.com/ '页是990869字节后
这段代码是我自己的(snippet_2),用于通过直接函数调用实现相同的工作。
import urllib.request
URLS = ['http://www.foxnews.com/',
'http://www.cnn.com/',
'http://europe.wsj.com/',
'http://www.bbc.co.uk/']
for url in URLS:
with urllib.request.urlopen(url, timeout=60) as conn:
print('%r page is %d bytes' % (url, len(data)))
print('after')
snippet_1似乎更常见,但是为什么呢?
当您从网络上读取内容时,您的应用程序可能会花费大部分时间等待答复。
通常,CPython内的全局解释器锁(您可能正在使用的Python实现)可确保一次仅一个线程在执行Python字节码。
但是,在等待I / O(包括网络I / O)时,将释放GIL,从而使其他线程有运行的机会。这意味着多个读取有效地并行运行,而不是一个接一个地运行,从而缩短了总体执行时间。
对于少数URI来说并没有多大区别。但是您使用的URI越多,它越引人注目。
因此,这ThreadPoolExecutor
对于并行运行I / O操作非常有用。在ProcessPoolExecutor
另一方面是并行运行CPU密集型任务非常有用。由于它使用多个进程,因此不适用GIL的限制。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句