コンテキスト マネージャー クラスを定義していますが、インスタンス化中に特定の条件が満たされた場合に例外を発生させずにコード ブロックをスキップできるようにしたいと考えています。たとえば、
class My_Context(object):
def __init__(self,mode=0):
"""
if mode = 0, proceed as normal
if mode = 1, do not execute block
"""
self.mode=mode
def __enter__(self):
if self.mode==1:
print 'Exiting...'
CODE TO EXIT PREMATURELY
def __exit__(self, type, value, traceback):
print 'Exiting...'
with My_Context(mode=1):
print 'Executing block of codes...'
ベストアンサー1
によるとペップ343、with
ある文は次のように翻訳されます:
with EXPR as VAR:
BLOCK
に:
mgr = (EXPR)
exit = type(mgr).__exit__ # Not calling it yet
value = type(mgr).__enter__(mgr)
exc = True
try:
try:
VAR = value # Only if "as VAR" is present
BLOCK
except:
# The exceptional case is handled here
exc = False
if not exit(mgr, *sys.exc_info()):
raise
# The exception is swallowed if exit() returns true
finally:
# The normal and non-local-goto cases are handled here
if exc:
exit(mgr, None, None, None)
ご覧のとおり、__enter__()
コンテキスト マネージャーのメソッドの呼び出しから、BLOCK
with ステートメントの本体 (" ") をスキップできる明らかな方法はありません。
__enter__()
次のようなプロジェクトでは、Python実装特有のこと、例えば内部のコールスタックを操作することなどが行われている。ハック付き1、2年前にAlex Martelliがstackoverflowに非常に興味深いwith-hackを投稿したのを覚えています(検索して見つけられるほど投稿内容をすぐには思い出せません)。
しかし、あなたの質問/問題に対する簡単な答えは、いわゆる「ディープ マジック」(Python 実装間で必ずしも移植可能ではない) に頼らずに、with ステートメントの本体をスキップして、あなたが求めていることを行うことはできないということです。ディープ マジックを使用すると、それが可能になるかもしれませんが、そのようなことは、それがどのように行われるかを確認するための練習としてのみ行うことをお勧めします。決して「製品コード」では行わないでください。