请考虑以下示例代码:
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。
现在,我想通过使用静态代码分析工具找到项目中在{em>>任何异常实例上调用.message
的所有位置。作为最终目标,我计划将此检查作为日常构建和测试及代码质量检查任务的一部分运行,并在语法仍然使用时引发错误。
有可能吗?它是pylint
,pyflakes
或其他代码分析工具能够实现的吗?
我发现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)并使我的测试失败,但这有其缺点:
答案 0 :(得分:7)
由于您希望静态地执行此操作,因此可以使用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
属性。