asyncio:我可以在异步中包装同步 REST 调用吗?
asyncio: Can I wrap a sync REST call in async?
asyncio:我可以在异步中包装同步 REST 调用吗? FTX fetch_position is a REST API call, it's not async and not awaitable. I tried below hoping if each call is 300ms, total not 300ms x3 = 900ms, but rather (wishful thinking) 300ms for all three using asyncio 魔法(协作式多任务处理)。但它没有用。总体耗时约 900 毫秒。我在这里做错了什么吗?
谢谢!
async def _wrapper_fetch_position(exchange : ccxt.Exchange):
pos = exchange.fetch_positions()
return pos
import asyncio
import nest_asyncio
loop = asyncio.get_event_loop()
nest_asyncio.apply()
pos1 = loop.run_until_complete(_wrapper_fetch_position(exchange1))
pos2 = loop.run_until_complete(_wrapper_fetch_position(exchange2))
pos3 = loop.run_until_complete(_wrapper_fetch_position(exchange3))
直接,不行,你会阻塞事件循环,得不到并发。但是,您可以将多线程与 asyncio 一起使用,使用 asyncio 的 to_thread
协程将同步调用包装在一个线程中。这将阻塞函数委托给 运行 在一个由 ThreadPoolExecutor
和 returns 可等待的单独线程支持,因此您可以在 await 表达式中使用它,就像它是非阻塞的一样。下面是使用 requests
库发出 20 个 Web 请求的示例,比较同步与线程:
import asyncio
import time
import requests
def in_sequence():
for i in range(20):
requests.get('https://www.example.com')
async def with_threads():
def make_request(): requests.get('https://www.example.com')
reqs = [asyncio.to_thread(make_request) for _ in range(20)]
await asyncio.gather(*reqs)
async def main():
sequence_start = time.time()
in_sequence()
sequence_end = time.time()
print(f'In sequence {sequence_end - sequence_start}')
thread_start = time.time()
await with_threads()
thread_end = time.time()
print(f'With threads {thread_end - thread_start}')
asyncio.run(main())
运行 在我的机器上,我得到以下结果,证明了性能差异:
In sequence 1.9963197708129883
With threads 0.26117658615112305
如果你想更好地控制线程池,你可以手动创建一个并使用asyncio的loop.run_in_executor方法。有关详细信息和如何使用它的示例,请参阅 https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor。
asyncio:我可以在异步中包装同步 REST 调用吗? FTX fetch_position is a REST API call, it's not async and not awaitable. I tried below hoping if each call is 300ms, total not 300ms x3 = 900ms, but rather (wishful thinking) 300ms for all three using asyncio 魔法(协作式多任务处理)。但它没有用。总体耗时约 900 毫秒。我在这里做错了什么吗? 谢谢!
async def _wrapper_fetch_position(exchange : ccxt.Exchange):
pos = exchange.fetch_positions()
return pos
import asyncio
import nest_asyncio
loop = asyncio.get_event_loop()
nest_asyncio.apply()
pos1 = loop.run_until_complete(_wrapper_fetch_position(exchange1))
pos2 = loop.run_until_complete(_wrapper_fetch_position(exchange2))
pos3 = loop.run_until_complete(_wrapper_fetch_position(exchange3))
直接,不行,你会阻塞事件循环,得不到并发。但是,您可以将多线程与 asyncio 一起使用,使用 asyncio 的 to_thread
协程将同步调用包装在一个线程中。这将阻塞函数委托给 运行 在一个由 ThreadPoolExecutor
和 returns 可等待的单独线程支持,因此您可以在 await 表达式中使用它,就像它是非阻塞的一样。下面是使用 requests
库发出 20 个 Web 请求的示例,比较同步与线程:
import asyncio
import time
import requests
def in_sequence():
for i in range(20):
requests.get('https://www.example.com')
async def with_threads():
def make_request(): requests.get('https://www.example.com')
reqs = [asyncio.to_thread(make_request) for _ in range(20)]
await asyncio.gather(*reqs)
async def main():
sequence_start = time.time()
in_sequence()
sequence_end = time.time()
print(f'In sequence {sequence_end - sequence_start}')
thread_start = time.time()
await with_threads()
thread_end = time.time()
print(f'With threads {thread_end - thread_start}')
asyncio.run(main())
运行 在我的机器上,我得到以下结果,证明了性能差异:
In sequence 1.9963197708129883
With threads 0.26117658615112305
如果你想更好地控制线程池,你可以手动创建一个并使用asyncio的loop.run_in_executor方法。有关详细信息和如何使用它的示例,请参阅 https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor。