修复MyPy报contextmanager返回psycopg2连接的cannot assign错误
报错原因
这个MyPy类型错误的根源是使用@contextmanager装饰的get_cnx()函数没有添加明确的返回值泛型标注,MyPy无法静态推断yield语句产出的对象实际类型,只能识别到contextmanager的泛型占位类型_T_co,因此判定传入some_function的参数类型不符合要求。
另外你贴出的get_cnx()实现存在两处会导致运行时报错的笔误:
psycopg2.poool拼写错误,正确模块路径为psycopg2.pool- 初始化连接池时赋值的变量名为
pool,后续调用getconn/putconn方法时使用的变量名是db_pool,变量名不匹配会触发NameError
修复方案
- 导入所需的类型依赖:
from contextlib import contextmanager # Python 3.9+ 从collections.abc导入Iterator,低版本从typing模块导入 from collections.abc import Iterator from psycopg2.extensions import connection import psycopg2.pool
- 给
get_cnx()添加明确的类型标注,告知类型检查器该上下文管理器产出的对象类型为connection,同时修正上述笔误:
@contextmanager def get_cnx(customer_id: int | str) -> Iterator[connection]: config: dict = <根据customer_id执行逻辑获取对应数据库连接配置> db_pool = psycopg2.pool.ThreadedConnectionPool(**config) cnx = db_pool.getconn() try: yield cnx finally: db_pool.putconn(cnx)
如果你更习惯用上下文管理器类型做标注,也可以从contextlib导入ContextManager,将返回类型写为ContextManager[connection],两种标注方式MyPy都可以正确识别。
完成标注后,with get_cnx() as conn:中的conn会被MyPy正确推断为psycopg2.extensions.connection类型,传入参数要求为connection | None的some_function时不会再触发类型错误,不需要通过# type: ignore强制忽略报错。
内容的提问来源于stack exchange,提问作者kravb
相关产品推荐
相关产品推荐

