python的异步C++库

Posted

技术标签:

【中文标题】python的异步C++库【英文标题】:Asynchronous C++ library for python 【发布时间】:2020-11-19 20:23:21 【问题描述】:

我正在努力解决一些问题,希望这里的人能够指导我完成。

我有一个异步 python 代码(asyncio),我用 C++ 编写了一个简单的异步客户端,与这个非常相似:https://www.boost.org/doc/libs/1_74_0/doc/html/boost_asio/example/cpp03/timeouts/async_tcp_client.cpp。出于测试目的,我有服务器,当客户端连接时,它每 x 秒向客户端发送一次消息。我的计划是能够从我的 python 代码中使用这个客户端,但问题是它目前阻塞了我的事件循环,我真的不知道该怎么处理它。有没有办法编写可以从 python 代码中等待的库?

示例 C++ 库:

void start_client(std::string ip, std::string port)

    try
    
        boost::asio::io_context io_context;
        tcp::resolver r(io_context);
        // https://www.boost.org/doc/libs/1_74_0/doc/html/boost_asio/example/cpp03/timeouts/async_tcp_client.cpp
        client c(io_context);

        c.start(r.resolve(ip, port));

        io_context.run();  // this will block :(
        
    
    catch (std::exception& e)
    
        std::cerr << "Exception: " << e.what() << "\n";
    



#include <pybind11/pybind11.h>


PYBIND11_MODULE(async_client, m) 
    m.def("start_client", &start_client);

还有一些最小的可重现 python 代码:

import asyncio
import async_client 


async def client():
    async_client.start_client('0.0.0.0', '3000')  # this will block :(


async def test():
    while True:
        print('This will not get displayed!')
        await asyncio.sleep(3)


async def main():
    await asyncio.gather(client(), test())

if __name__ == '__main__':
    asyncio.run(main())

我已经尝试过释放 GIL 并在不同的线程中运行 io_context,但我仍然需要一些无休止的进程,这样它就不会跳出范围并且仍然会阻塞。

m.def("start_client", &start_client, pybind11::call_guard<pybind11::gil_scoped_release>() );

感谢任何提示,谢谢。

【问题讨论】:

你能提供一个complete, minimal, and reproducible 的例子吗? C++ IO 代码本身是异步的吗?读写时使用阻塞调用还是非阻塞调用? 【参考方案1】:

要使start_client 不阻塞事件循环,您需要释放 GIL,并将其交给由 asyncio 管理的线程池(执行程序):

async def client():
    loop = asyncio.get_event_loop()
    await loop.run_in_executor(
        None, async_client.start_client, '0.0.0.0', '3000'
    )

理想情况下,可以连接 asyncio 和 boost_asio 事件循环,这样就不需要线程,但这样做可能是一项重大任务。

【讨论】:

以上是关于python的异步C++库的主要内容,如果未能解决你的问题,请参考以下文章

小白学 Python 爬虫(32):异步请求库 AIOHTTP 基础入门

异步请求Python库 grequests的应用和与requests库的响应速度的比较

Python啥爬虫库好用?

关于Redis Python 异步 Client

用于运行异步请求的 Python Celery 与线程库 [关闭]

python如何调用C++外部库中的类?