python 3.5+ 中 pycurl 的异步替代方案

Async alternative to pycurl in python 3.5+

我有一个 discord 机器人,我怀疑它由于 pycurl 偶尔的缓慢调用而定期出现问题。经过一些研究,我发现 pycurl 不是异步的,这可能是我遇到麻烦的原因。

我有这个功能:

def communicate_wallet(wallet_command):
    buffer = BytesIO()
    c = pycurl.Curl()
    c.setopt(c.URL, '[::1]')
    c.setopt(c.PORT, 7076)
    c.setopt(c.POSTFIELDS, json.dumps(wallet_command))
    c.setopt(c.WRITEFUNCTION, buffer.write)
    c.perform()
    c.close()

    body = buffer.getvalue()
    parsed_json = json.loads(body.decode('iso-8859-1'))
    return parsed_json

这相当于一个 curl 命令,如:

curl -g -d '{ "action": "action_def" }' '[::1]:7076'

我想知道是否有异步替代方法来执行此操作,因此我可以使用 await 调用 communicate_wallet。我似乎找不到 pycurl 的任何异步兼容替代品。

谢谢

Tornado 包似乎有你想要的 tornado.curl_httpclient.CurlAsyncHTTPClient 形式。

I'm wondering if there's an async alternative to do this, so i can call communicate_wallet with await.

最简单的选择是使用 run_in_executor 作为拦截代码:

loop = asyncio.get_event_loop()
data = await loop.run_in_executor(None, communicate_wallet, wallet_command)

这会将阻塞函数提交到线程池并在完成时唤醒您的协程,同时允许 asyncio 处理它的业务。

更好的方法是将pycurl替换为原生支持asyncio的http客户端,例如aiohttp。最初这将需要更多的工作,但可能会在长期 运行 中得到回报,因为它将允许 http 代码通过 asyncio 与任务 运行 通信而无需线程同步。