我想在Python 3.7中创建一个多进程理解。
这是我的代码:
async def _url_exists(url):
"""Check whether a url is reachable"""
request = requests.get(url)
return request.status_code == 200:
async def _remove_unexisting_urls(rows):
return {row for row in rows if await _url_exists(row[0])}
rows = [
'http://example.com/',
'http://example.org/',
'http://foo.org/',
]
rows = asyncio.run(_remove_unexisting_urls(rows))
在此代码示例中,我想从列表中删除不存在的URL。 (请注意,我使用的是集合而不是列表,因为我也想删除重复项。)
我的问题是我仍然看到执行是顺序执行的。 HTTP请求使执行等待。 与串行执行相比,执行时间是相同的。
答案 0 :(得分:1)
asyncio
本身不会并发运行不同的async
函数。但是,使用multiprocessing
模块的Pool.map
,您可以安排函数在另一个进程中运行:
from multiprocessing.pool import Pool
pool = Pool()
def fetch(url):
request = requests.get(url)
return request.status_code == 200
rows = [
'http://example.com/',
'http://example.org/',
'http://foo.org/',
]
rows = [r for r in pool.map(fetch, rows) if r]
答案 1 :(得分:1)
requests
不支持asyncio
。如果要进行真正的异步执行,则必须查看aiohttp或asks
应该在卸载任务之前构建您的集合,这样您甚至不必执行重复操作,而是简化结果。
使用requests
本身,您可以退回到run_in_executor
,它将在ThreadPoolExecutor内执行您的请求,因此不是真正的异步I / O:
import asyncio
import time
from requests import exceptions, get
def _url_exists(url):
try:
r = get(url, timeout=10)
except (exceptions.ConnectionError, exceptions.ConnectTimeout):
return False
else:
return r.status_code is 200
async def _remove_unexisting_urls(l, r):
# making a set from the list before passing it to the futures
# so we just have three tasks instead of nine
futures = [l.run_in_executor(None, _url_exists, url) for url in set(r)]
return [await f for f in futures]
rows = [ # added some dupes
'http://example.com/',
'http://example.com/',
'http://example.com/',
'http://example.org/',
'http://example.org/',
'http://example.org/',
'http://foo.org/',
'http://foo.org/',
'http://foo.org/',
]
loop = asyncio.get_event_loop()
print(time.time())
result = loop.run_until_complete(_remove_unexisting_urls(loop, rows))
print(time.time())
print(result)
输出
1537266974.403686
1537266986.6789136
[False, False, False]
如您所见,初始化线程池会有一定的损失,在这种情况下约为2.3秒。但是,考虑到这三个任务中的每一个都会运行十秒钟直到超时(我的IDE不允许通过代理),所以整个十二秒钟的执行时间看起来是相当并行的。