python - 检查弃用警告的代码

标签 python python-2.7 static-code-analysis deprecation-warning

考虑以下示例代码:

data = []
try:
    print data[0]
except IndexError as error:
    print error.message

代码在语法上没有任何错误(使用 Python2.7),除非你运行 python with warnings turned on。 , 你会看到一个 DeprecationWarning:

$ python -W always test.py
test.py:5: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
  print error.message
list index out of range

仅供引用,这是因为 .message was deprecated since python2.6 and removed in python3 .

现在,我想通过使用静态代码分析 工具找到项目中所有在任何异常实例上调用.message 的地方。作为最终目标,我计划将此检查作为每日构建&测试&代码质量检查任务的一部分运行,如果语法仍在使用,则会引发错误。

这可能吗? pylintpyflakes 或其他代码分析工具能够做到这一点吗?


我发现 pep8 tool实现了几个类似的检查,例如,has_key() usage check:

$ cat test.py
my_dict = {}
print my_dict.has_key('test')
$ pep8 test.py
test.py:2:14: W601 .has_key() is deprecated, use 'in'

作为替代解决方案,我可以将所有警告视为错误(如建议的 here )并使我的测试失败,但这有其缺点:

  • 我无法修复来自第三方包的其他弃用警告
  • 严格来说,这需要100%的覆盖率,很难维护

最佳答案

因为您想静态地执行此操作,您可以使用 ast 模块来解析代码,然后使用 NodeVisitor类。像这样:

import ast, sys

class UsingMessageAttr(ast.NodeVisitor):

    error_object_names = []

    def visit_Attribute(self, node):
        if (node.attr == 'message' and 
            hasattr(node.value, 'id') and 
            node.value.id in self.error_object_names):

            print("Danger Will Robinson!!")
            sys.exit(1)

        self.generic_visit(node)

    def visit_ExceptHandler(self, node):
        if node.name is not None:
            self.error_object_names.append(node.name)
            self.generic_visit(node)
            self.error_object_names.pop()
        else:
            self.generic_visit(node)

with open('sourcefile.py', 'r') as f:
    UsingMessageAttr().visit(ast.parse(f.read()))

这是通过使用 python 将源文件解析为 AST,然后使用访问者模式遍历整个文件并找到已弃用属性的任何实例来实现的。有关其工作原理的更多信息,请参阅 the python documentation on the ast module .

请注意,如果您使用一些巧妙的方法来引用异常对象,这将不起作用。它只是获取异常对象绑定(bind)到的变量名,并检查是否曾经从异常处理程序主体内的同名变量访问过 message 属性。

关于python - 检查弃用警告的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27242434/

相关文章:

c - 夹板如何进行污点分析

erlang - 选择 AST 来为 Elixir 开发静态代码分析器?核心 Erlang 还是扩展的 Elixir AST?

Python:正则表达式:使用一个正则表达式检测连字符的名称和非连字符的名称

Python:使用MySql数据库的Django框架

python - 在 Python 3 中重现 Python 2 PyQt4 QImage 构造函数行为

基于 Sublime Text 3 的 Python 2.7 不打印 '\uFFFD' 字符

scala - 如何修复有关 asInstanceOf 使用的警告

python - 如何在 Windows 上使用 Python 将 SQLite 2 转换为 SQLite3?

python - 为什么不能用urlencode编码json格式的数据?

python - Selenium with Python - Chromedriver 必须在 PATH 中