我在python中编程相当新,我已经编程了半年左右。我决定尝试建立一个功能性交易机器人。在尝试编写这个机器人时,我偶然发现了asyncio模块。我真的想更好地理解这个模块,但很难找到关于asyncio的任何简单的教程或文档。
对于我的剧本,我每个硬币收集音量。这非常有效,但收集所有卷需要很长时间。我想问一下我的脚本是否同步运行,如果是这样,我该如何解决?我使用API包装器与Binance Exchange进行通信。
import binance
import asyncio
import time
s = time.time()
names = [name for name in binance.ticker_prices()] #Gathering all the coin names
loop = asyncio.get_event_loop()
async def get_volume(name):
async def get_data():
return binance.ticker_24hr(name) #Returns per coin a dict of the data of the last 24hr
data = await get_data()
return (name, data['volume'])
tasks = [asyncio.ensure_future(get_volume(name)) for name in names]
results = loop.run_until_complete(asyncio.gather(*tasks))
print('Total time:', time.time() - s)
答案 0 :(得分:1)
由于binance.ticker_24hr
看起来不像是一个协程,因此它几乎肯定会阻止事件循环,从而阻止asyncio.gather
完成其工作。作为快速修复,您可以使用run_in_executor
在单独的线程中运行阻止功能:
async def get_volume(name):
loop = asyncio.get_event_loop()
data = await loop.run_in_executor(None, binance.ticker_24hr, name)
return name, data['volume']
这适用于合理数量的并行任务。缺点是它使用线程,因此可能无法扩展到大量并行请求(或者需要不必要的等待)。从长远来看,正确的解决方案是使用本机支持asyncio的库。
答案 1 :(得分:0)
Maarten首先要为每个符号调用get_ticker,这意味着你要做出许多不必要的请求。如果您在没有符号值的情况下调用它,则可以在一个请求中获取所有代码。如果您没有执行其他任务,这也会删除任何循环或异步。看起来您正在使用的binance库并不支持此功能。您可以使用python-binance来执行此操作
return client.get_ticker()
那说我一直在测试python-binance的asyncio版本。如果您想尝试它,它现在正处于功能分支中。
pip install git+https://github.com/sammchardy/python-binance@feature/asyncio
包含客户端的asyncio版本并初始化客户端
from binance.client_async import AsyncClient as Client
client = Client("<api_key>", "<api_secret>")
然后你可以等待电话获取特定符号的代码
return await client.get_ticker(symbol=name)
或者对于所有符号代码,不要传递符号参数
return await client.get_ticker()
希望有所帮助