python - asyncio:我可以在异步中包装同步 REST 调用吗?
问题描述
asyncio:我可以在异步中包装同步 REST 调用吗?FTX fetch_position 是一个 REST API 调用,它不是异步的,也不是可等待的。我在下面尝试了希望每个调用是否为 300 毫秒,总计不是 300 毫秒 x3 = 900 毫秒,而是(一厢情愿)所有三个使用asyncio魔法(协作多任务)的 300 毫秒。但它没有用。总体耗时约 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 一起使用,将同步调用包装在带有 asyncioto_thread
协程的线程中。这会委托一个阻塞函数在由 a 支持的单独线程中运行ThreadPoolExecutor
并返回一个可等待对象,因此您可以在 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
If you want more control over the thread pool, you can manually create one and use asyncio's loop.run_in_executor method. See https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor for more details and an example on how to use this.
推荐阅读
- java - 如何在 application-{profile}.properties 文件中包含 log4j-{profile}.properties 文件
- mysql - 使用 Group By 查询具有多个条件的多个列
- r - R data.table - 如何分解嵌套数组?
- pdf - TCPdf 在多个页面中将自定义作者或页面添加到页脚(每个页面上的作者/页面可以不同)
- sql - 从 oracle 触发器发送电子邮件 - 如果发生任何 DML
- ios - TableViewController 选择性单元格在表格重新加载时被取消选择
- amazon-web-services - AWS X-RAY 在同时获取跟踪摘要时显示奇怪的错误
- c++ - 在函数参数中区分数组和指针 - C++
- android - 为什么位置getTime滞后2-3分钟
- mysql - 无法在创建 MySQL 服务器的同一计划中使用 mysql