Python 3 的类型检查工具
Type checking tool for Python 3
我正在尝试 运行 一个命令,该命令在作为目录提供的某些 Python 源代码中提供有关类型检查、静态代码分析等的一些汇总信息。如果存在这样的东西,那么我想将它添加到 Makefile
在某些 CI 管道期间调用以验证代码库。
我创建了这个带有运行时间问题
的虚拟源代码文件
文件foo_sample.py
def foo_func(my_num):
return 1 + my_num
def bar_func():
foo_func("foo")
if __name__ == "__main__":
bar_func()
它抛出这个 运行时间错误:
TypeError: unsupported operand type(s) for +: 'int' and 'str'.
现在我尝试用各种工具来检测这种类型错误,但他们都没有发现这类问题。请参阅以下列表中的命令:
pyflakes foo_sample.py
,
flake8 foo_sample.py
,
pylint foo_sample.py
,
mypy --check-untyped-defs foo_sample.py
,
prospector --strictness veryhigh foo_sample.py
我知道我可以用 unittest
检测到这些问题,但是代码库相当大并且在某种程度上未经测试。我们经常看到 运行 时间错误,并通过单元测试或集成测试解决它们。但是,我们希望在 CI 管道执行期间检测到它们。
有没有办法在 运行 代码本身之前 运行 这些类型的检查?
如何避免在 运行 时发现这些错误?
未声明的类型被认为是 Any
类型,并且不会被 mypy
类型检查。需要更严格的配置以确保 mypy
强制您设置类型。具体来说,您需要 disallow_untyped_defs
,这会导致您得到以下结果:
$ cat test.py
def foo_func(my_num: int) -> int:
return 1 + my_num
def bar_func() -> None:
foo_func("foo")
if __name__ == "__main__":
bar_func()
$ mypy test.py
test.py:6: error: Argument 1 to "foo_func" has incompatible type "str"; expected "int"
Found 1 error in 1 file (checked 1 source file)
您可能还想要 disallow_any_generics
and warn_return_any
. Example configuration。
我发现 pytype 在这种情况下很有用。
在此代码上调用 pytype broken_code.py
时:
def foo_func(my_num):
return 1 + my_num
def bar_func():
foo_func("foo")
def run_func(my_func):
my_func()
if __name__ == "__main__":
bar_func()
run_func(bar_func())
我在输出中正确找到:
line 3, in foo_func: unsupported operand type(s) for +: 'int' and 'str' [unsupported-operands]
line 10, in run_func: 'NoneType' object is not callable [not-callable]
该命令以错误退出,因此 Makefile
调用它可能会阻止在 CI 环境中执行管道。
此外,可以通过代码中的注释启用或禁用像 [unsupported-operands]
等错误检查,例如
- 首先禁用检查
# pytype: disable=attribute-error
- 然后再次启用检查
# pytype: enable=attribute-error
在文档中查看如何使用这些注释,Error classes。
我正在尝试 运行 一个命令,该命令在作为目录提供的某些 Python 源代码中提供有关类型检查、静态代码分析等的一些汇总信息。如果存在这样的东西,那么我想将它添加到 Makefile
在某些 CI 管道期间调用以验证代码库。
我创建了这个带有运行时间问题
的虚拟源代码文件文件foo_sample.py
def foo_func(my_num):
return 1 + my_num
def bar_func():
foo_func("foo")
if __name__ == "__main__":
bar_func()
它抛出这个 运行时间错误:
TypeError: unsupported operand type(s) for +: 'int' and 'str'.
现在我尝试用各种工具来检测这种类型错误,但他们都没有发现这类问题。请参阅以下列表中的命令:
pyflakes foo_sample.py
,flake8 foo_sample.py
,pylint foo_sample.py
,mypy --check-untyped-defs foo_sample.py
,prospector --strictness veryhigh foo_sample.py
我知道我可以用 unittest
检测到这些问题,但是代码库相当大并且在某种程度上未经测试。我们经常看到 运行 时间错误,并通过单元测试或集成测试解决它们。但是,我们希望在 CI 管道执行期间检测到它们。
有没有办法在 运行 代码本身之前 运行 这些类型的检查?
如何避免在 运行 时发现这些错误?
未声明的类型被认为是 Any
类型,并且不会被 mypy
类型检查。需要更严格的配置以确保 mypy
强制您设置类型。具体来说,您需要 disallow_untyped_defs
,这会导致您得到以下结果:
$ cat test.py
def foo_func(my_num: int) -> int:
return 1 + my_num
def bar_func() -> None:
foo_func("foo")
if __name__ == "__main__":
bar_func()
$ mypy test.py
test.py:6: error: Argument 1 to "foo_func" has incompatible type "str"; expected "int"
Found 1 error in 1 file (checked 1 source file)
您可能还想要 disallow_any_generics
and warn_return_any
. Example configuration。
我发现 pytype 在这种情况下很有用。
在此代码上调用 pytype broken_code.py
时:
def foo_func(my_num):
return 1 + my_num
def bar_func():
foo_func("foo")
def run_func(my_func):
my_func()
if __name__ == "__main__":
bar_func()
run_func(bar_func())
我在输出中正确找到:
line 3, in foo_func: unsupported operand type(s) for +: 'int' and 'str' [unsupported-operands]
line 10, in run_func: 'NoneType' object is not callable [not-callable]
该命令以错误退出,因此 Makefile
调用它可能会阻止在 CI 环境中执行管道。
此外,可以通过代码中的注释启用或禁用像 [unsupported-operands]
等错误检查,例如
- 首先禁用检查
# pytype: disable=attribute-error
- 然后再次启用检查
# pytype: enable=attribute-error
在文档中查看如何使用这些注释,Error classes。