如何将asyncio与外部事件循环集成



我正在编写一个事件驱动的程序,该程序使用C编写事件调度。该程序使用Python作为扩展模块。我想允许扩展模块使用async/await语法来实现协同程序。Coroutines将只与我的程序的部分交互,不涉及IO。我的C调度程序是单线程的,我需要协程在它的线程中执行。

在纯Python程序中,我只需按原样使用asyncio,并让我的程序使用其事件循环来驱动所有事件。然而,这不是一种选择;我的事件循环每秒需要服务数百万个基于C的事件,我负担不起Python的开销。

我尝试编写自己的事件循环实现,它将所有调度委托给我的C调度器。我尝试了几种方法:

  • 重新实现EventLoopFutureTask等,以模仿asyncio的工作方式(减去IO(,使call_soon将调度委托给我的C事件循环。这是安全的,但需要一些工作,而且在文档、调试支持、复杂的语义细节和正确性/测试覆盖率方面,我的实现总是不如asyncio
  • 我可以使用asyncio中的普通TaskFuture等,并且只创建AbstractEventLoop的自定义实现,以相同的方式将调度委派给我的C事件循环。这很简单,但我可以看到普通的EventLoop访问不明显的内部(task._source_traceback_asyncgen_finalizer_hook_set_running_loop(,所以我的实现仍然是第二类的。我还必须依靠未记录的Handle._run来实际调用回调
  • 如果我从BaseEventLoop而不是AbstractEventLoop进行子类化,事情似乎会变得越来越好(但文档说我不应该这么做(。不过,我仍然需要Handle._run
  • 我可以生成一个单独的线程,run_forever:s是一个普通的asyncio.DefaultEventLoop,并在那里运行我所有的协程,但协程依赖于我程序的扩展API,它不支持并发调用。所以我必须以某种方式使DefaultEventLoop在调用Handle._run()时暂停我的C事件循环。我看不出有什么合理的方法可以做到这一点

关于如何最好地做到这一点,有什么想法吗?其他人是如何解决这个问题的?

我发现trioasyncio的第三方替代方案,它通过所谓的来宾模式为与外部事件循环的集成提供了明确的支持。解决了我的问题!

最新更新