web-dev-qa-db-ja.com

Python-アサートとイフ&リターン

テキストファイルに対して何かを行うスクリプトを書いています(それが何をするかは私の質問には関係ありません)。ファイルに何かをする前に、ファイルが存在するかどうかを確認したいと思います。私はこれを行うことができます、問題はありませんが、問題はより美学の問題です。

これは、2つの異なる方法で同じものを実装する私のコードです。

def modify_file(filename):
    assert os.path.isfile(filename), 'file does NOT exist.'


Traceback (most recent call last):
  File "clean_files.py", line 15, in <module>
    print(clean_file('tes3t.txt'))
  File "clean_files.py", line 8, in clean_file
    assert os.path.isfile(filename), 'file does NOT exist.'
AssertionError: file does NOT exist.

または:

def modify_file(filename):
    if not os.path.isfile(filename):
        return 'file does NOT exist.'


file does NOT exist.

最初の方法では、ほとんど取るに足らない出力が生成されますが、私が気にしているのは、ファイルが存在しないことだけです。

2番目のメソッドは文字列を返します。これは簡単です。

私の質問は次のとおりです。ファイルが存在しないことをユーザーに知らせるには、どちらの方法が適していますか? assertメソッドの使用は、どうやらPythonicのようです。

13
Vader

代わりにthirdオプションを使用します。raiseと特定の例外を使用します。これは 組み込みの例外 のいずれかであるか、またはジョブのカスタム例外を作成できます。

この場合、私は IOError を使用しますが、 ValueError も適合する可能性があります。

_def modify_file(filename):
    if not os.path.isfile(filename):
        raise IOError('file does NOT exist.')
_

特定の例外を使用すると、さまざまな例外状況でother例外を発生させ、呼び出し元が例外を適切に処理できるようになります。

もちろん、多くのファイル操作(open()など)自体はすでにOSErrorを発生させます。ファイルが存在するかどうかを最初に明示的にテストすることは、ここでは冗長になる場合があります。

assertは使用しないでください。 pythonを_-O_フラグ付きで実行すると、すべてのアサーションがコードから削除されます。

34
Martijn Pieters

assertは、serとは対照的に、programmer関数の呼び出しでエラーが発生した場合を対象としています。そのような状況でassertを使用すると、プログラマーがテスト中に関数を正しく使用していることを確認できますが、本番環境ではそれを取り除きます。

コードを介してそのパスを確実に実行する必要があるため、その値は多少制限されます。また、本番環境で別のifステートメントを使用して問題をさらに処理したい場合がよくあります。 assertは次のような場合に最も役立ちます。「ユーザーがこの問題にぶつかった場合、この問題を効果的に回避したいが、開発者がこの問題にぶつかった場合、ハードクラッシュして、これを呼び出すコードを修正する正しく機能しません。」

特定のケースでは、ファイルの欠落はほぼ間違いなくユーザーエラーであり、例外を発生させることによって処理する必要があります。

12
Karl Bielefeldt

From singAssertionsEffectively

Isinstance()のチェックは過度に使用しないでください。アヒルのようにうなずく場合は、実際にそうであるかどうかを深く調べる必要はないでしょう。元のプログラマが予期していなかった値を渡すと便利な場合があります。

アサーションの配置を検討する場所:

checking parameter types, classes, or values
checking data structure invariants
checking "can't happen" situations (duplicates in a list, contradictory state variables.)
after calling a function, to make sure that its return is reasonable 

全体的なポイントは、何か問題が発生した場合、できるだけ早くそれを完全に明らかにしたいということです。

後で問題が発生したときに、どのようにしてそこに到達したかを調べるよりも、誤ったデータをその時点でキャッチする方が簡単です。

アサーションは、単体テストやシステムテストの代わりではなく、補足です。アサーションはオブジェクトまたは関数の内部状態を調べるためのクリーンな方法であるため、外部動作を調べるブラックボックステストに「無料」でクリアボックスアシスタンスを提供します。

アサーションはnotを使用して、不正なユーザー入力やオペレーティングシステム/環境のエラー(ファイルが見つからないなど)が原因で発生する可能性のあるエラーのケースをテストする必要があります。代わりに、例外を発生させるか、エラーメッセージまたは適切なものを出力する必要があります。アサーションをプログラムのセルフテストにのみ使用すべき重要な理由の1つは、アサーションをコンパイル時に無効にできることです。

Pythonが-Oオプションで開始されている場合、アサーションは取り除かれ、評価されません。そのため、コードがアサーションを頻繁に使用するが、パフォーマンスが重要である場合、それらをオンにするシステムがあります。 (ただし、本当に必要な場合を除いて、これを行わないでください。一部のバグは、お客様がマシンを使用していて、アサーションもそれを助けたい場合にのみ表示されることが科学的に証明されています。:-))

5
dspjm