-with-ブロックの実行をスキップする 質問する

-with-ブロックの実行をスキップする 質問する

コンテキスト マネージャー クラスを定義していますが、インスタンス化中に特定の条件が満たされた場合に例外を発生させずにコード ブロックをスキップできるようにしたいと考えています。たとえば、

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

によるとペップ343withある文は次のように翻訳されます:

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__()コンテキスト マネージャーのメソッドの呼び出しから、BLOCKwith ステートメントの本体 (" ") をスキップできる明らかな方法はありません。

__enter__()次のようなプロジェクトでは、Python実装特有のこと、例えば内部のコールスタックを操作することなどが行われている。ハック付き1、2年前にAlex Martelliがstackoverflowに非常に興味深いwith-hackを投稿したのを覚えています(検索して見つけられるほど投稿内容をすぐには思い出せません)。

しかし、あなたの質問/問題に対する簡単な答えは、いわゆる「ディープ マジック」(Python 実装間で必ずしも移植可能ではない) に頼らずに、with ステートメントの本体をスキップして、あなたが求めていることを行うことはできないということです。ディープ マジックを使用すると、それが可能になるかもしれませんが、そのようなことは、それがどのように行われるかを確認するための練習としてのみ行うことをお勧めします。決して「製品コード」では行わないでください。

おすすめ記事