Cython下iscoroutinefunction函数不可用
前言
今天使用 Cython 编译 py 文件到 pyd 文件,使用生成好的 pyd 文件时报了异常,异常信息比较奇怪,所以研究了一下。
问题分析
需要编译的 py 文件所有代码都是异步,使用到了 asyncio 和一个异步的 opc client,和下位 PLC 进行交互。打包过程略去不表,后面单独写文章阐述打包方法和过程。
在导入生成的 pyd 文件后,运行程序,发现报了异常,异常信息为:
1 | asyncua\common\subscription.py:126: RuntimeWarning: coroutine 'AndonInteractive.datachange_notification' was never awaited |
既然给出了异常文件和对应位置,那么就找到文件看看代码好了。
根据提示,找到了异常位置,如图:
异常提示在 126 行,异常信息提示异步代码没有使用 await,也就是说上方的 if 判断为 False。但是我写的回调函数的确是一个异步函数,按理说不应该走到图中红框的代码处,而且不使用 pyd 文件的话程序是正常运行的,也没有报错,说明问题出现在编译成 pyd 文件之后。
所以这里猜测 asyncio.iscoroutinefunction
可能在 Cython 中失效了,或者支持的不完善导致 if 判断结果本应该为 True 走上边的分支,结果却为 False,走到了下面的错误分支。
确认猜想
为了确认猜测是否正确,还得去搜索一下,当然不能直接搜索异常信息,由于这里是一个比较特殊的原因导致报了一个很常见的异常,所以搜索时需要带上 Cython 和 iscoroutinefunction
才能搜索到有用的结果,搜索结果如下:
前几条结果非常精确的匹配了我们需要寻找的内容,例如这里,这里,这里,经过查找,发现这是一个已知问题,并且已经存在了不短的时间了,从 2018 年就开始有人提 issues,解决方案到最近才被合并到 Cython 的主分支,对应 PR 在这。
解决问题
既然已经被合并到了主分支,那么为什么我下载最新版的 Cython 编译后还是得到了错误的结果呢?我去翻了翻 Cython 的更新日志,发现我现在使用的是 Cython 的正式版,版本号为 0.29.21,而 alpha 版本都已经到 3.0.0 alpha 7 了,alpha 7 版本刚刚修复这个问题,但是还没有发布到 pypi 上,如图:
由于 alpha 7 版本暂未发布,发布时间还没定,所以暂时无法直接从 pypi 安装 alpha 7 版本,如果想要使用最新版本只能自己编译安装最新版的 Cython。
所以我们首先需要将 Cython 依赖从 requirements.txt 文件中去掉,之后在依赖安装过程中 clone Cython 的源码,通过 python setup.py install
命令编译安装最新版的 Cython,之后再运行编译脚本编译 pyd 文件,修改后的持续集成配置文件如下:
1 | name: build Python Package |
重新运行持续集成任务,测试 exe 文件,异常信息消失,问题解决。
总结
本篇文章通过一个很奇怪的异常信息顺藤摸瓜找到了异常的原因和解决方案,目前的解决方案还只是一个临时的解决方案,等 Cython 发布 3.0 正式版即可。
本文章首发于个人博客 LLLibra146’s blog
本文作者:LLLibra146
更多文章请关注:
版权声明:本博客所有文章除特别声明外,均采用 © BY-NC-ND 许可协议。非商用转载请注明出处!严禁商业转载!
本文链接:
https://blog.d77.xyz/archives/6e0c75f4.html