10

次のサンプル コードを検討してください。

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

警告をオンにして python を実行すると、次のように表示されることを除いて、コードに構文的に問題はありません (Python2.7 を使用) 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

参考までに、これは.messagepython2.6 から廃止され、 python3 で削除されたためです。

ここで、静的コード分析ツールを使用.messageして、例外インスタンスで呼び出されるプロジェクト内のすべての場所を見つけたいと思います。最終的な目標として、このチェックを毎日のビルドとテストとコードの品質チェック タスクの一部として実行し、構文がまだ使用されている場合はエラーを発生させることを計画しています。

出来ますか?それはpylintpyflakesまたは他のコード分析ツールで可能なものですか?


pep8ツール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'

別の解決策として、すべての警告をエラーとして扱い (ここで提案されているように)、テストを失敗させることができますが、これには欠点があります。

  • 修正できないサードパーティ製パッケージからの非推奨の警告が他にもある
  • 厳密に言えば、これには 100% のカバレッジが必要であり、これを維持することは困難です。
4

1 に答える 1

8

これを静的に行う必要があるため、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 に解析し、次にビジター パターンを使用してファイル全体をウォークスルーし、廃止された属性のインスタンスを見つけることによって機能します。この仕組みの詳細については、ast モジュールの python ドキュメントを参照してください。

例外オブジェクトを参照するために巧妙なものを使用すると、これは機能しないことに注意してください。例外オブジェクトがバインドされた変数名を取得し、message属性が例外ハンドラーの本体内の同じ名前の変数からアクセスされるかどうかを確認します。

于 2014-12-06T21:35:15.707 に答える