收集硬币卷 - 我的代码是否异步运行?

时间:2018-04-15 22:40:57

标签: python-asyncio

我在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)

2 个答案:

答案 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()

希望有所帮助