Cython编译的asyncio gRPC Python服务运行异常问题求助
问题根因
你遇到的报错本质是Cython默认编译配置下,async def定义的协程方法、async def + yield定义的异步生成器方法会被编译为C层级的函数对象,丢失了Python原生协程/异步生成器的类型标识。gRPC异步服务端在调用服务方法前,会通过反射判断方法类型决定是否需要await,识别不到Cython编译后的协程标识时,会直接当作普通同步方法调用,直接返回了协程/异步生成器对象,没有执行await操作,就触发了你看到的两类报错。
同步gRPC版本没有问题是因为同步方法不需要识别协程标识,直接调用即可,不受Cython编译的影响。
解决方案
不需要修改业务代码,只需要调整Cython编译参数,开启binding配置即可,该配置会让Cython编译出的函数保留Python原生函数的全部属性标识,gRPC就能正常识别协程/异步生成器类型。
修改你的build.sh中的cython编译命令,增加-X binding=True参数:
#!/bin/sh # 新增-X binding=True参数 cython -3 -X binding=True --embed --output-file srv.c srv.py gcc $(pkg-config --cflags python3) srv.c -o srv -lpython3.8
如果你不想全局开启该配置,也可以在srv.py文件头部加一行Cython指令注解,效果完全一致:
# cython: binding = True import asyncio import grpc # 其余业务代码不变
验证
修改后重新执行build.sh编译,再启动服务端,客户端调用即可恢复正常,不会再出现协程未await、异步生成器不可迭代的报错。
内容的提问来源于stack exchange,提问作者Slava Zhuyko
相关产品推荐
相关产品推荐

