You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用mypy检测含pysnmp-lextudio的Python项目时出现name-defined错误怎么办?

解决pysnmp-lextudio与mypy类型检查的name-defined错误

在依赖pysnmp-lextudio的Python项目中运行mypy类型检查时,会出现大量name-defined错误,但代码实际可正常运行,且Pylance能识别相关定义。另外,必须给导入语句加# type: ignore,否则会触发import-untyped错误(提示模块缺失类型存根或py.typed标记)。

问题重现步骤

poetry new pysnmp-and-mypy
cd ./pysnmp-and-mypy
poetry add mypy
poetry add pysnmp-lextudio
touch ./pysnmp_and_mypy/test.py

将以下代码写入./pysnmp_and_mypy/test.py:

from pysnmp.hlapi import *  # type: ignore
from typing import Any


def convert_snmp_type_to_python_type(
    snmp_value: Integer32 | Integer | Unsigned32 | Gauge32 | OctetString | Any,
) -> int | str:
    match snmp_value:
        case Integer32():
            return int(snmp_value)
        case Integer():
            return int(snmp_value)
        case Unsigned32():
            return int(snmp_value)
        case Gauge32():
            return int(snmp_value)
        case OctetString():
            return str(snmp_value)
        case _:
            raise TypeError(
                "Only SNMP types of type integer and string are supported. Received type of {}".format(
                    str(type(snmp_value))
                )
            )


def get_data(ip_address: str, object_identity: str) -> int | str:
    iterator = getCmd(
        SnmpEngine(),
        CommunityData("public", mpModel=0),
        UdpTransportTarget((ip_address, 161)),
        ContextData(),
        ObjectType(ObjectIdentity(object_identity)),
    )

    error_indication, error_status, error_index, variable_bindings = next(iterator)

    if error_indication:
        raise RuntimeError(error_indication.prettyPrint())
    elif error_status:
        raise RuntimeError(error_status.prettyPrint())
    else:
        [variable_binding] = variable_bindings
        [_oid, value] = variable_binding
        return convert_snmp_type_to_python_type(value)

执行检查命令:

poetry install
poetry run mypy ./pysnmp_and_mypy

错误信息

pysnmp_and_mypy\test.py:6: error: Name "Integer32" is not defined  [name-defined]
pysnmp_and_mypy\test.py:6: error: Name "Integer" is not defined  [name-defined]
pysnmp_and_mypy\test.py:6: error: Name "Unsigned32" is not defined  [name-defined]
pysnmp_and_mypy\test.py:6: error: Name "Gauge32" is not defined  [name-defined]
pysnmp_and_mypy\test.py:6: error: Name "OctetString" is not defined  [name-defined]
pysnmp_and_mypy\test.py:9: error: Name "Integer32" is not defined  [name-defined]
pysnmp_and_mypy\test.py:11: error: Name "Integer" is not defined  [name-defined]
pysnmp_and_mypy\test.py:13: error: Name "Unsigned32" is not defined  [name-defined]
pysnmp_and_mypy\test.py:15: error: Name "Gauge32" is not defined  [name-defined]
pysnmp_and_mypy\test.py:17: error: Name "OctetString" is not defined  [name-defined]
pysnmp_and_mypy\test.py:28: error: Name "getCmd" is not defined  [name-defined]
pysnmp_and_mypy\test.py:29: error: Name "SnmpEngine" is not defined  [name-defined]
pysnmp_and_mypy\test.py:30: error: Name "CommunityData" is not defined  [name-defined]
pysnmp_and_mypy\test.py:31: error: Name "UdpTransportTarget" is not defined  [name-defined]
pysnmp_and_mypy\test.py:32: error: Name "ContextData" is not defined  [name-defined]
pysnmp_and_mypy\test.py:33: error: Name "ObjectType" is not defined  [name-defined]
pysnmp_and_mypy\test.py:33: error: Name "ObjectIdentity" is not defined  [name-defined]

问题原因

  1. pysnmp-lextudio未提供py.typed标记或官方类型存根,mypy默认会跳过对这类无类型模块的分析。
  2. 你添加的# type: ignore会让mypy完全忽略该导入语句的所有类型检查,导致它无法识别从pysnmp.hlapi导入的类和函数名称。
  3. Pylance依靠动态类型推断和内置的第三方库类型提示机制,因此能识别这些名称,不受类型存根缺失的影响。

解决方案

方案1:安装第三方类型存根(优先尝试)

查找社区维护的pysnmp类型存根包,比如types-pysnmp,通过poetry安装:

poetry add --dev types-pysnmp

安装后移除导入语句的# type: ignore,重新运行mypy检查即可。

方案2:手动编写项目级类型存根

如果没有合适的第三方类型存根,可以在项目中创建自定义类型存根:

  1. 在项目根目录创建typings/pysnmp/hlapi.pyi文件,内容如下:
from typing import Iterator, Tuple, Type

class Integer32:
    def __int__(self) -> int: ...

class Integer:
    def __int__(self) -> int: ...

class Unsigned32:
    def __int__(self) -> int: ...

class Gauge32:
    def __int__(self) -> int: ...

class OctetString:
    def __str__(self) -> str: ...

class SnmpEngine:
    def __init__(self) -> None: ...

class CommunityData:
    def __init__(self, community: str, mpModel: int) -> None: ...

class UdpTransportTarget:
    def __init__(self, addr: Tuple[str, int]) -> None: ...

class ContextData:
    def __init__(self) -> None: ...

class ObjectIdentity:
    def __init__(self, oid: str) -> None: ...

class ObjectType:
    def __init__(self, oid: ObjectIdentity) -> None: ...

def getCmd(
    engine: SnmpEngine,
    data: CommunityData,
    transport: UdpTransportTarget,
    context: ContextData,
    obj_type: ObjectType
) -> Iterator[Tuple[object, object, object, object]]: ...
  1. 在项目的pyproject.toml中添加mypy配置,指定类型存根路径:
[tool.mypy]
mypypath = ["typings"]
strict = true # 保持原有严格检查,根据需求调整
  1. 移除导入语句的# type: ignore,重新运行mypy检查。

方案3:放宽mypy检查规则(不推荐)

如果以上方案都无法实施,可以通过mypy参数放宽检查,但会降低类型检查的有效性:

poetry run mypy --ignore-missing-imports --follow-imports=silent ./pysnmp_and_mypy

或者在pyproject.toml中配置:

[tool.mypy]
ignore_missing_imports = true
follow_imports = "silent"

最佳替代方案

如果不想编写完整的类型存根,可结合typing.TYPE_CHECKING和字符串类型注解,仅在类型检查阶段提供类型信息:

from pysnmp.hlapi import *  # type: ignore[import-untyped]
from typing import Any, TYPE_CHECKING

if TYPE_CHECKING:
    # 仅在类型检查时导入,不影响运行时
    from pysnmp.hlapi import (
        Integer32, Integer, Unsigned32, Gauge32, OctetString,
        getCmd, SnmpEngine, CommunityData, UdpTransportTarget,
        ContextData, ObjectType, ObjectIdentity
    )

def convert_snmp_type_to_python_type(
    snmp_value: "Integer32 | Integer | Unsigned32 | Gauge32 | OctetString | Any",
) -> int | str:
    match snmp_value:
        case Integer32():
            return int(snmp_value)
        case Integer():
            return int(snmp_value)
        case Unsigned32():
            return int(snmp_value)
        case Gauge32():
            return int(snmp_value)
        case OctetString():
            return str(snmp_value)
        case _:
            raise TypeError(
                "Only SNMP types of type integer and string are supported. Received type of {}".format(
                    str(type(snmp_value))
                )
            )

# get_data函数保持不变

这种方式既能让mypy识别类型,又不影响代码运行,同时仅忽略特定的import-untyped错误,保留其他类型检查。

内容的提问来源于stack exchange,提问作者bmitc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 17:19:51