我尝试了python请求库文档中提供的示例:
http://docs.python-requests.org/en/latest/user/advanced/#asynchronous-requests
与async.map(rs)我得到的响应代码,但我想请求每一页的内容.
out = async.map(rs)
print out[0].content
Run Code Online (Sandbox Code Playgroud)
例如,只是不工作.
我正在尝试将此Python2.7代码重写为新的异步世界顺序:
def get_api_results(func, iterable):
pool = multiprocessing.Pool(5)
for res in pool.map(func, iterable):
yield res
Run Code Online (Sandbox Code Playgroud)
map()阻塞直到计算完所有结果,所以我试图将其重写为异步实现,一旦准备就会产生结果.同样map(),返回值必须按照与之相同的顺序返回iterable.我试过这个(我需要requests因为传统的身份验证要求):
import requests
def get(i):
r = requests.get('https://example.com/api/items/%s' % i)
return i, r.json()
async def get_api_results():
loop = asyncio.get_event_loop()
futures = []
for n in range(1, 11):
futures.append(loop.run_in_executor(None, get, n))
async for f in futures:
k, v = await f
yield k, v
for r in get_api_results():
print(r)
Run Code Online (Sandbox Code Playgroud)
但是使用Python 3.6我得到了:
File "scratch.py", line 16, in <module>
for r in …Run Code Online (Sandbox Code Playgroud) 我需要使用Requests库发出异步请求。在Python 3.7中,如果尝试from requests import async得到SyntaxError: invalid syntax。
async已在Python 3.7中保留。如何解决这种情况?
我在Python 3.6中编写了一个工具,它向几个API(带有各种端点)发送请求,并收集它们的解析来解析并将它们保存在数据库中.
我使用的API客户端具有请求URL 的同步版本,例如他们使用的
urllib.request.Request('...
或者他们使用Kenneth Reitz的Requests图书馆.
由于我的API调用依赖于请求URL的同步版本,因此整个过程需要几分钟才能完成.
现在我想将我的API调用包装在async/await(asyncio)中.我正在使用python 3.6.
我发现的所有示例/教程都要我将同步URL调用/ requests更改为异步版本(例如aiohttp).由于我的代码依赖于我未编写的API客户端(我无法更改),因此我需要保持该代码不受影响.
那么有没有办法将我的同步请求(阻塞代码)包装在async/await中以使它们在事件循环中运行?
我是Python新手中的asyncio.这在NodeJS中是不费脑子的.但是我不能用Python来解决这个问题.
一旦所有HTTP请求返回,我想启动大量HTTP请求并收集其结果。使用可以以非阻塞方式发送请求asyncio,但是我在收集其结果时遇到问题。
我知道针对此特定问题而设计的解决方案,例如aiohttp。但是HTTP请求只是一个例子,我的问题是如何asyncio正确使用。
在服务器端,我有flask可以localhost/用“ Hello World!” 回答每个请求,但是要等待0.1秒再回答。在所有示例中,我正在发送10个请求。同步代码大约需要1秒钟,异步版本则可以在0.1秒内完成。
在客户端,我想同时启动许多请求并收集其结果。我正在尝试以三种不同的方式来做到这一点。由于asyncio需要执行者来解决阻塞代码,因此所有方法都调用loop.run_in_executor。
这些代码在它们之间共享:
import requests
from time import perf_counter
import asyncio
loop = asyncio.get_event_loop()
async def request_async():
r = requests.get("http://127.0.0.1:5000/")
return r.text
def request_sync():
r = requests.get("http://127.0.0.1:5000/")
return r.text
Run Code Online (Sandbox Code Playgroud)
方法1:
asyncio.gather()在任务列表中使用,然后单击run_until_complete。阅读Asyncio.gather与asyncio.wait之后,似乎collect会等待结果。但事实并非如此。因此,此代码立即返回,而无需等待请求完成。如果我在此处使用阻止功能,则可以正常工作。为什么我不能使用异步功能?
# approach 1
start = perf_counter()
tasks = []
for i in range(10):
tasks.append(loop.run_in_executor(None, request_async)) # <---- using async function !
gathered_tasks = asyncio.gather(*tasks)
results = loop.run_until_complete(gathered_tasks) …Run Code Online (Sandbox Code Playgroud) 使用 asyncio async/await 和 Python 3.7+ 提供 100k API 调用的最佳方法是什么?想法是始终并行使用 100 个任务?
应该避免的是:
1. 开始处理所有 100k 任务
2. 等待所有 100 个并行任务完成,以便安排新的 100 个任务。
这个例子说明了第一种方法,这不是所需要的。
import aiohttp
import asyncio
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
urls = [
'http://python.org',
'https://google.com',
'http://yifei.me'
]
tasks = []
async with aiohttp.ClientSession() as session:
for url in urls:
tasks.append(fetch(session, url))
htmls = await asyncio.gather(*tasks)
for html in htmls:
print(html[:100])
if __name__ == '__main__':
loop …Run Code Online (Sandbox Code Playgroud) 我想在龙卷风的异步GET请求处理程序中运行一个缓慢的阻止方法(实际上是从第三方库中)。将该方法设为:
def blocking_method(uid):
print("slow method started: ", uid)
time.sleep(10)
print("slow method done: ", uid)
return "slow method ({}) result".format(uid)
Run Code Online (Sandbox Code Playgroud)
此外,我更喜欢在asyncio的事件循环中运行龙卷风服务器:
if __name__ == '__main__':
tornado.platform.asyncio.AsyncIOMainLoop().install()
loop = asyncio.get_event_loop()
loop.run_until_complete(make_app())
loop.run_forever()
Run Code Online (Sandbox Code Playgroud)
我知道@run_in_executor装饰器,但是它不适合我,因为我使用asyncio。要在异步协程中运行阻止方法,应使用的run_in_executor方法asyncio.get_event_loop()。这是一个示例,如何从此答案中做到这一点:
import asyncio
async def main():
loop = asyncio.get_event_loop()
executor = concurrent.futures.ThreadPoolExecutor(max_workers=4)
future1 = loop.run_in_executor(executor, blocking_method, 1)
future2 = loop.run_in_executor(executor, blocking_method, 2)
response1 = await future1
response2 = await future2
print(response1)
print(response2)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)
而且效果很好,这是先前脚本的输出:
slow …Run Code Online (Sandbox Code Playgroud) python ×6
async-await ×3
asynchronous ×3
python-3.x ×2
coroutine ×1
generator ×1
grequests ×1
httprequest ×1
python-3.7 ×1
tornado ×1