【问题标题】:Checking code for deprecation warnings检查弃用警告的代码
【发布时间】:2015-01-30 06:53:41
【问题描述】:

考虑以下示例代码:

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() 使用检查:

$ 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%的覆盖率,很难维护

【问题讨论】:

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


    【解决方案1】:

    由于您想静态地执行此操作,您可以使用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

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

    【讨论】:

    • 我猜,换句话说,答案是:“不,没有工具可以帮助你,你应该自己做”:) 非常感谢您的指点!跨度>
    • @alecxe 没问题,我希望有人会过来并给出一个简单的答案(这对于如此简单的事情来说似乎太难了)但就是这样。不过还不错,我给你的代码作为独立脚本可能工作得很好(也许你可以从sys.argv 获取源文件名并输出带有错误消息的行号)。
    • 是否可以添加自定义警告消息? (如果是:在哪里/如何?)通过 PyDev
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多