Pythonでアサーションを無効にするにはどうすればよいですか?
つまり、アサーションが失敗した場合、アサーションがスローするのAssertionError
ではなく、続行する必要があります。
それ、どうやったら出来るの?
回答:
Pythonでアサーションを無効にするにはどうすればよいですか?
単一のプロセス、環境、または1行のコードに影響を与える複数のアプローチがあります。
それぞれを実演します。
-O
フラグ(大文字のO)を使用すると、プロセス内のすべてのアサートステートメントが無効になります。
例えば:
$ python -Oc "assert False"
$ python -c "assert False"
Traceback (most recent call last):
File "<string>", line 1, in <module>
AssertionError
無効とは、それに続く式も実行しないことを意味することに注意してください。
$ python -Oc "assert 1/0"
$ python -c "assert 1/0"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
環境変数を使用して、このフラグを設定することもできます。
これは、環境を使用または継承するすべてのプロセスに影響します。
たとえば、Windowsでは、環境変数を設定してからクリアします。
C:\>python -c "assert False"
Traceback (most recent call last):
File "<string>", line 1, in <module>
AssertionError
C:\>SET PYTHONOPTIMIZE=TRUE
C:\>python -c "assert False"
C:\>SET PYTHONOPTIMIZE=
C:\>python -c "assert False"
Traceback (most recent call last):
File "<string>", line 1, in <module>
AssertionError
Unixでも同じ(それぞれの機能にsetとunsetを使用)
あなたはあなたの質問を続けます:
アサーションが失敗した場合、AssertionErrorをスローしたくはありませんが、続行します。
実行に失敗したコードが必要な場合は、制御フローがアサーションに到達しないようにすることができます。次に例を示します。
if False:
assert False, "we know this fails, but we don't get here"
または、アサーションエラーをキャッチできます。
try:
assert False, "this code runs, fails, and the exception is caught"
except AssertionError as e:
print(repr(e))
印刷するもの:
AssertionError('this code runs, fails, and the exception is caught')
を処理した時点から続行しますAssertionError
。
次のようなassertステートメント:
assert expression #, optional_message
と同等です
if __debug__:
if not expression: raise AssertionError #(optional_message)
そして、
組み込み変数
__debug__
は、最適化が要求されたときのTrue
通常の状況下にありますFalse
(コマンドラインオプション-O
)。
そしてさらに
への割り当て
__debug__
は違法です。組み込み変数の値は、インタープリターの起動時に決定されます。
使用法のドキュメントから:
基本的な最適化をオンにします。これにより、コンパイルされた(バイトコード)ファイルのファイル名拡張子が.pycから.pyoに変更されます。PYTHONOPTIMIZEも参照してください。
そして
これが空でない文字列に設定されている場合は、
-O
オプションを指定することと同じです。整数に設定すると、-O
複数回指定するのと同じです。
if False: assert False
)、アサーションエラーをキャッチすることができます。それらはあなたの選択です。あなたの質問に対処するために答えを更新しました。
foo()
れますwith skip_assertion(): foo()
。アサーションをオフに切り替えます。私は機能上の別のフラグを追加するために持っていけないことは、この存在の恩恵
Assert
オブジェクトをPass
オブジェクトに置き換える)。コンテキストマネージャーはそのために直接機能しませんが、そのように装飾された関数を使用するある種のメカニズムを持つことができます。とにかく、私はそれをお勧めしません。あなたがそうしたい理由は、あなたが制御していないコードを呼び出して、AssertionErrorsを取得しているからだと思います。もしそうなら、あなたはおそらく別の修正を見つける必要があります。
-Oフラグを指定してPythonを呼び出します。
test.py:
assert(False)
print 'Done'
出力:
C:\temp\py>C:\Python26\python.exe test.py
Traceback (most recent call last):
File "test.py", line 1, in <module>
assert(False)
AssertionError
C:\temp\py>C:\Python26\python.exe -O test.py
Done
すでに与えられている2つの答えは両方とも有効です(いずれか-O
または-OO
コマンドラインでPythonを呼び出します)。
それらの違いは次のとおりです。
-O
基本的な最適化をオンにします。これにより、コンパイルされた(バイトコード)ファイルのファイル名拡張子が.pycから.pyoに変更されます。
-OO
docstringを破棄する -O
最適化に加えて、をます。
(Pythonドキュメントから)
(ほとんどの)アサーションを無効にしないでください。注意が他の場所にある場合、それらは予期しないエラーをキャッチします。「10の累乗」のルール5を参照してください。
代わりに、次のような方法でいくつかの高価なアサーションチェックを保護します。
import logging
logger = logging.getLogger(__name__)
if logger.getEffectiveLevel() < logging.DEBUG:
ok = check_expensive_property()
assert ok, 'Run !'
重要なアサーションを保持し、assert
ステートメントを最適化できるようにする1つの方法は、選択ステートメント内でそれらを上げることです。
if foo_is_broken():
raise AssertionError('Foo is broken!')
__debug__
Falseに設定してみましたが、許可されていません。