将Python asyncio接口与Cython库一起使用

0x00

我有一个用Cython包装的C ++外部库。我无法更改此C ++库本身。我想合并该库,以用作使用asyncio作为其主要过程控件的Python应用程序的一部分。

Cython库实际上使用专有协议来进行网络工作。但是,当在python中启动库的事件处理程序时,Cython库将阻塞。我已经达到了可以传递Python函数并接收从C ++库接收到的事件的回调的阶段。如果在event_loop.run_in_executor中运行事件处理程序,则可以解析将应用程序挂在库事件处理程序上的库。

我的问题是,我该如何最好地对此模型进行建模以使其与接口很好地兼容,而不是破解临时解决方案以使用Cython库方法?我看过将其编写为asyncio.Protocol和asyncio.Transport,然后将Cython库用作其基础通信机制。但是,看起来有些费劲,但有些猴子修补使它看起来像一个插槽。是否有更好的方法或抽象将包装器放在外部库上以使其与asyncio一起使用?

0x00

据我所知,回答我自己的问题,没有义务使用异步中的协议或传输提供的抽象来构造应用程序。我发现的最佳建模方法是使用常规类,并将其方法定义为异步。然后可以使该类看起来像符合您要求的任何模式。如果您要包装的代码与套接字的总体用例不同,则这尤其重要。异步提供的抽象本身只是一个准系统。对于像Cython包装的C ++阻塞代码这样的复杂事物,您将需要通过多处理来处理它。这是为了避免挂起解释器。Asyncio无法在没有更改的情况下运行阻塞代码。该代码必须专门编写为与asyncio兼容。

我所做的就是将整个阻塞代码(包括对象的构造)放入使用event_loop.run_in_executor执行的函数中。除此之外,我还使用unix套接字与命令和回调数据的进程进行通信。由于使用unix套接字,因此您可以在主应用程序中使用asnycio方法,管道也是如此。

这是我从多进程Process产生器向asyncio主进程发送128字节后得到的结果。数据以10毫秒的间隔生成。持续时间是使用time.perf_counter()计时的。以下结果以纳秒为单位。机器本身是运行Linux内核4.10.17的Intel®Core™i7-2600 CPU @ 3.40GHz。

带有uvloop的Asyncio

计数10001.000000
平均值76435.956504 
std 8887.459462
最小值63608.000000 
25%71709.000000 
50%74104.000000 
75%79496.000000
最大值287204.000000

标准Asyncio事件循环

计数10001.000000
均值199741.937506 
std 27900.377114
分钟173321.000000 
25%185545.000000 
50%191839.000000 
75%205279.000000
最大529246.000000

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章