Python中用于静态types检查的工具

我正在使用一个庞大的现有的Python代码库,并希望开始添加types注释,所以我可以得到一定程度的静态检查。 我在想像Erlang , Strongtalk或Typed Scheme / Racket 。

我见过快速和脏的装饰器插入基于函数参数和返回types注释的dynamic检查,但我正在寻找更强大的东西,并在编译时执行检查。

现在有什么工具可用于这种事情? 我熟悉编译器和types检查,如果它有一个良好的基础,我肯定会改进一个不完整的工具。

(注意:我对静态types优劣的讨论不感兴趣。)

编辑 :一个例子:

def put(d, k, v): d[k] = v 

我希望能够注释put函数的types是put<K,V>(dict<K,V>, K, V) -> None

更新 :新的PEP 484 (2014年9月)在Python 3.5+中为静态types和types注释定义了一个标准。 有一个types检查工具称为mypy ,与PEP 484兼容。

编辑2016-11-11:只需使用mypy 。 types提示可以逐渐添加。 在Python 3源代码中,它validation标准的PEP 484types提示。 types仍然可以使用特殊注释在Python 2中表示。 Guido喜欢它 。

这个post最初是在mypy之前写的。 我保留下面的post的原创内容,即使它不是很准确。


原文:

对于Python的静态分析,您可能想要查看一些在这个相关的StackOverflow文章中提到的项目。

综上所述:

  • pylint的
  • PyFlakes
  • PyChecker

由于Python广泛使用鸭子打字 ,所以在其他语言中可能被称为“types错误”的东西可能最终是Python中的“对象X不支持方法Y ”。

编辑2011-05-17:

我同意delnan,静态types是不可能的Python [显然是错] 。 但是由于我们的怀疑似乎不能阻止你,所以我只能给你提供更多关于这个问题的信息。 有请:

  • Python的types推断的讨论。 (其他链接来自这里)
  • Guido van van Rossum关于添加可选静态types的文章: 第1 部分和第2部分 。
  • RPython是Python的一个子集,可能有足够的静态分析的可能性来进行某种forms的types检查。

你可能会发现mypy有趣。 已经提议将Guido包含在Python 3.5中 。

看看这篇文章: PySonar:Python的静态分析器 。 PySonar是一个使用抽象解释(部分执行)来推断types的工具。 它find你的程序的所有可能的执行path,并find所有variables的所有可能的types。

基本上有三个版本的PySonar:

  • 开源的Java(Jython索引器)
  • 封闭源Java(隐藏在Google中)
  • 开源的Python( 迷你pysonar )

没有一个(封闭源除外)全部实施。 但基本的想法是,你可以用它作为你工作的基础。

我不知道这是否有帮助,但是为了什么是值得的,科罗拉多大学的杰里米·谢克(Jeremy Siek)做了一些逐步打字的工作,我发现这个快速search。 pdf/28_Siek_gradual.pdf

我的猜测(我可能是错的)是因为他的研究看起来相对较新,目前还没有任何有前途的开源工具。

您最好的select可能是联系作者,询问他们是否可以向您发布代码。

有Python 3的“渐进”包, 请参阅PIP或Bitbucket回购

显然,这是围绕杰里米·西克 ( Jeremy Siek )的一个实施组织,他似乎是逐渐打字领域的权威。

一些注释显然是必要的,这里是一个例子:

 from gradual import * @typed def calculate_total(a:int, b:int) -> int: return a + b//100 

就注释而言,这并不是那么糟糕。 我没有使用这个包,所以我不能说它的质量,但语法(和它背后的人)肯定使它看起来很有前途。

我喜欢探矿者 , landscape.io的后端。 它将现有分析仪的输出(如pylint,pyflakes,pep8,frosted …)组合成一个报告。 整齐。

前段时间我也有类似的需求。 我发现的所有现有的解决scheme都有一些问题,或者没有我想要的function,所以我已经做出了自己的解决scheme。

以下是你如何使用它:

 from requiretype import require @require(name=str, age=(int, float, long)) def greet_person(name, age): print "Hello {0} ({1})".format(name, age) >>> greet_person("John", 42) Hello John (42) >>> greet_person("John", "Doe") # [...traceback...] TypeError: Doe is not a valid type. Valid types: <type 'int'>, <type 'float'>, <type 'long'> >>> greet_person(42, 43) # [...traceback...] TypeError: 42 is not a <type 'str'> type 

我希望这对你有用。

更多细节请看:

PS :(引用自己的github回购)

对于大多数情况下,我build议使用testing,而不是types检查,因为在Python中这是更自然的。 但是,在某些情况下,你想/需要指定一个特定的types来使用,因为python没有参数types检查这里是有用的。