请问使用asyncio时如何搭配各种第三方库呢?

小弟最近开始学习使用python3.6的asyncio库,掌握了基本使用之后却发现实际应用中不知如何下手,其中一个最大的原因就是小弟经常会需要使用各种第三方库,例如ssh用的paramiko,ftp用的ftputil,等等等等…这些第三方库是否能够和asyncio很好的契合在一起呢?如何判断我是否能在asyncio中使用一个第三方库呢?请大大给支个招吧,谢谢大家

阅读 3.2k
2 个回答

首先,最简单的办法就是搜一下这个库的源码里是否出现了 asyncioasync def 的字样,如果没有出现则几乎可以证明这个库没有对 asyncio 有做特别的支持。为了彻底证实,还应仔细阅读其代码,查看关键 I/O 部分是如何实现的。

对于暂不支持 asyncio 的第三方库,可以按以下步骤依次排查:

  1. 确认其 I/O 时间比例是否占到大部分。比如用 SQLAlchemy 时,如果能基本上确保数据库操作都是瞬时的,那么理论上是可以任由其阻塞主线程的。而对于明显 I/O 占大多数时间且时间不可预测的,比如 requests,就不能让其成为性能瓶颈;
  2. 确认其 I/O 的并发能力是否会成为瓶颈。比如说还是用到了 requests,但平均下来每 10 分钟才会发一个请求,其他时间主要都用在数据库计算上了,那么完全可以把 requests 放到线程池里去做;
  3. 确实需要异步了,首先查找其 asyncio 的扩展,有时会有单独的库做 asyncio 支持,比如 peewee_async;
  4. 查找其 asyncio 的替代,比如用 asyncpg 替代 psycopg2;
  5. 实在没有了,再次看看线程池的解决方案对性能的影响到底是多少;
  6. 如果线程池确实不行,此时一般碰到的库多半都会有自己的并发模型,走到这一步意味着该并发模型并不能兼容 asyncio。此时,可以看看并发库对 asyncio 的支持,比如 gevent 与 asyncio 的桥接
  7. 自己改了它吧,或者造新的轮子。
新手上路,请多包涵

一般的库都应该是同步的,除非明确说是异步的。

  • 文件描述符要 NON BLOCKING,如果不 NON BLOCKING,神仙也异步不起来,所以在建立描述符的时候一定要看支持 NON BLOCKING 吗,当然从操作系统层面来讲,一定是支持的。
  • 异步编程机制的整合,这就是题主所问。如果一个库本来是同步的,并且也设置了non blocking,那么就要把这个文件描述符加入 ioloop 之中,asyncio 的 event loop 一定支持动态加文件描述符的,了解一下 select 或者 poll 这样的系统调用你就明白了。这样 asyncio 的 loop 就会 watch 你的文件描述符了。
  • 返回 Future 对象,这个跟操作系统无关,完全是上层设计模式,类似 Javascript 的 Deferred 对象,这是 Future 对象就是说这个玩意过会儿被设备(你文件描述符指向)Resolve,你无法知道,但是你可以等它 Resolved 给你通知。在你的文件描述符产生事件对应的 callback 中 Resolve Future 对象,让你的调用者收到结果。简单说写一个函数返回 一个 Future 对象,然后想办法在文件描述的事件 callback 中 Resovle这个对象。因为你的 IO 操作都 non blocking 了所以马上返回 Future了。
  • 返回 Future 对象的函数 就是可以 wait 的函数了,现在你应该可以把一个本来是同步的第三方库改造或者封装成异步库了。
  • 要理解清楚最好看看 select epoll 之类的系统调用,看看网卡驱动,TCP IP 实现,socket 抽象之类的,这样更容易理解。
  • 什么时候建立描述符,怎么构造 Future,这是跟设计有关,完全随便搞,当然逻辑上可能是荒唐的,技术上没有问题。比如你做一个数据库连接池,服务很多客户,那么这些 non blocking 操作的 callback 和 future 对象如果搭错了线,张冠李戴完全可能。
推荐问题
宣传栏