Python 添加类型信息而不依赖于类型模块

Python 添加类型信息而不依赖于类型模块,python,typing,mypy,typeshed,Python,Typing,Mypy,Typeshed,我一直在向包的.py文件中添加类型信息,以支持对包运行mypy。除此之外,还允许为这个第三方软件包生成信息 由于我的包必须与Python 2.7兼容,因此我使用注释作为类型信息: def __init__(self, s): # type: (Text) -> None 但为了运行mypy这需要我导入键入: from typing import Text, IO, BinaryIO, Union 这导致两个问题: 这在Python 3.5.0和3.5.1上不起作用,因为它有一个

我一直在向包的
.py
文件中添加类型信息,以支持对包运行
mypy
。除此之外,还允许为这个第三方软件包生成信息

由于我的包必须与Python 2.7兼容,因此我使用注释作为类型信息:

def __init__(self, s):
    # type: (Text) -> None
但为了运行
mypy
这需要我导入键入:

from typing import Text, IO, BinaryIO, Union
这导致两个问题:

  • 这在Python 3.5.0和3.5.1上不起作用,因为它有一个模块
    键入
    ,但不包括
    文本
    。从PyPI安装并不能解决这个问题。(还有一些用户在该版本的Python上运行该包)

  • 这使得我的包依赖于2.7/3.3/3.4安装,需要额外的下载和安装

  • 我定义了自己的
    联合
    类型:

    StreamType = Union[BinaryIO, IO[str], StringIO]
    StreamTextType = Union[Text, StreamType]
    
    根据输入是否可用,必须有条件地执行此代码

  • 对于第一个问题,由于我没有在Python 3.5.0/1下运行
    mypy
    ,因此我可以执行以下操作:

    import sys
    if sys.version_info < (3, 5, 0) and sys.version_info >= (3, 5, 2):
        from typing import Text, IO, BinaryIO, Union
    
    将导致
    mypy
    抛出错误
    未定义名称“Text”

    第三个问题可以通过使用
    try
    -
    来解决,除了
    (丑陋,也可能低效),或者例如通过测试环境变量(也可以用于解决第一个问题)

    运行
    mypy
    时是否设置了一个环境变量,我可以对其进行测试,以便仅在运行
    mypy
    时执行import语句? 针对环境变量进行测试还允许我将自己类型的定义放在“受保护”的范围内


    或者其他解决方案?

    mypy
    关联的唯一环境变量是
    MYPYPATH
    ,该变量由包的代码读取,而不是由它设置。虽然可以设置
    MYPYPATH
    (尤其是在生成
    typeshed
    信息时,以提供“其他”类型信息),但不能保证它是正确的

    您不能注释掉
    import
    语句,但可以将其放入从不执行的块中:

    if False:  # MYPY
        from typing import Text, IO, BinaryIO, Union
    
    这样做的好处是,如果在特定的Python文件中不需要导入
    os
    来获取环境变量(和/或
    sys
    来获取
    version\u info

    您的类型定义也应该这样指定,并且可以在导入或定义所有使用的类型后的任何位置出现:

    # import or define StringIO
    
    if False:  # MYPY
        StreamType = Union[BinaryIO, IO[str], StringIO]
        StreamTextType = Union[Text, StreamType]
    
    如果上述文件位于
    mytypes.py
    中,则在任何类型定义中使用
    StreamTypeText
    的程序包中的任何其他源文件都应执行以下操作:

    if False:  # MYPY
        from typing import Text, IO, BinaryIO, Union
        from .mytypes StreamType
    
    上述内容将满足
    mypy
    ,因此不会对未定义的
    文本引发错误。它还可以在3.5.0/1上使用,并且不需要让您的包依赖于
    键入

    如果要在Python2.7环境中运行
    mypy
    ,您可能仍然需要安装
    typing
    ,但正常软件包的用户不会受到影响

    注意,我在每个块的
    if
    之后添加了注释
    #MYPY
    。从键入的
    中搜索
    文件很容易,但是如果
    mypy
    改变了其行为,并且您的代码需要进行调整,那么使用
    StreamType
    的块就不那么容易找到了

    if False:  # MYPY
        from typing import Text, IO, BinaryIO, Union
        from .mytypes StreamType