9

考慮下面的示例代碼:檢查代碼

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),並我的測試失敗,但這有其缺點:

  • 還有其他的棄用警告來自第三方軟件包,我不能f九
  • 嚴格地說,這需要100%的覆蓋率,這是難以維持

回答

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屬性。

+0

我想,換句話說,得到的答覆是說:「沒有,沒有工具,它可以幫助你,你應該讓自己」 :)非常感謝您的指點! – alecxe 2014-12-11 05:35:20

+0

@alecxe沒問題,我希望有人會一起來,並給出一個簡單的答案(這似乎太難以實現這麼簡單),但就是這樣。雖然這並沒有那麼糟糕,但我給你的代碼可能會作爲一個獨立的腳本很好地工作(也許你可以從'sys.argv'獲得源文件名並輸出你的錯誤消息的行號)。 – randomusername 2014-12-11 06:02:20

+0

是否可以添加自定義警告消息? (如果是:在哪裏/如何?)要顯示例如由PyDev – hardmooth 2016-06-01 12:00:46