使用**kwargs调用DirectConnectClient方法时mypy类型不兼容错误的解决方法(无法修改目标函数定义)
我之前也碰到过boto3和mypy配合时的这种类型检查问题,尤其是用**kwargs传递参数的时候,明明逻辑没问题,但mypy就是报错。针对你遇到的这个情况,这里有几个不需要修改原方法定义的解决方案:
方案1:显式传参(最直观,推荐)
既然你只需要传递directConnectGatewayId和可选的virtualGatewayId,完全可以不用kwargs,直接分支处理显式传参,这样mypy的类型检查会直接通过,代码可读性也更好:
def _describe_assoc( dxgw_id: str, vpgw_id: str = "" ) -> DescribeDirectConnectGatewayAssociationsResultTypeDef: client: DirectConnectClient = boto3.client("directconnect") if vpgw_id: return client.describe_direct_connect_gateway_associations( directConnectGatewayId=dxgw_id, virtualGatewayId=vpgw_id ) return client.describe_direct_connect_gateway_associations( directConnectGatewayId=dxgw_id )
方案2:用类型断言告诉mypy kwargs的正确类型
如果你坚持要用kwargs,可以通过类型断言让mypy明白你的字典结构和方法参数类型兼容。因为boto3的describe_direct_connect_gateway_associations方法接受的参数大多是Optional[str]类型(除了maxResults是Optional[int],但你没用到),所以可以把kwargs断言成对应的字典类型:
from typing import cast, Dict, Optional def _describe_assoc( dxgw_id: str, vpgw_id: str = "" ) -> DescribeDirectConnectGatewayAssociationsResultTypeDef: kwargs = cast(Dict[str, Optional[str]], {"directConnectGatewayId": dxgw_id}) if vpgw_id: kwargs["virtualGatewayId"] = vpgw_id client: DirectConnectClient = boto3.client("directconnect") return client.describe_direct_connect_gateway_associations(**kwargs)
这里的cast会告诉mypy:“放心,这个字典的value都是可选字符串,符合方法的参数要求”,从而绕过错误提示。
方案3:自定义TypedDict定义kwargs结构(更严谨)
如果想让类型检查更严谨,可以用TypedDict来定义kwargs的预期结构,这样mypy会自动验证你添加的键值对是否符合要求:
from typing import TypedDict class DescribeAssocKwargs(TypedDict, total=False): directConnectGatewayId: str virtualGatewayId: str def _describe_assoc( dxgw_id: str, vpgw_id: str = "" ) -> DescribeDirectConnectGatewayAssociationsResultTypeDef: kwargs: DescribeAssocKwargs = {"directConnectGatewayId": dxgw_id} if vpgw_id: kwargs["virtualGatewayId"] = vpgw_id client: DirectConnectClient = boto3.client("directconnect") return client.describe_direct_connect_gateway_associations(**kwargs)
total=False表示这个TypedDict的键都是可选的,刚好匹配方法的可选参数特性。
为什么会出现这个错误?
mypy默认会推断你的kwargs是Dict[str, str]类型,但boto3的方法参数定义里,这些参数的类型是Optional[str](甚至还有maxResults这种Optional[int]类型)。mypy担心你可能会传入不符合类型要求的键值对,所以抛出了类型不兼容的错误。上面的方案都是通过明确类型信息,让mypy信任你的参数结构是合法的。
内容的提问来源于stack exchange,提问作者Alex Harvey

