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
这导致两个问题:
键入
,但不包括文本
。从PyPI安装并不能解决这个问题。(还有一些用户在该版本的Python上运行该包)联合
类型:
StreamType = Union[BinaryIO, IO[str], StringIO]
StreamTextType = Union[Text, StreamType]
根据输入是否可用,必须有条件地执行此代码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