Break or exit out of “with” statement?

后端 未结 12 2163
伪装坚强ぢ
伪装坚强ぢ 2020-12-02 11:04

I\'d just like to exit out of a with statement under certain conditions:

with open(path) as f:
    print \'before condition\'
    if 

        
相关标签:
12条回答
  • 2020-12-02 11:31

    Since break can only occur inside a loop your options are somewhat limited inside the with to:

    • return (put "with" + associated statements inside function)
    • exit (bail from program - probably not ideal)
    • exception (generate exception inside "with", catch below)

    Having a function and using return is probably the cleanest and easiest solution here if you can isolate the with and the associated statements (and nothing else) inside a function.

    Otherwise generate an exception inside the with when needed, catch immediately below/outside the with to continue the rest of the code.

    Update: As OP suggests in the comments below (perhaps tonuge in cheek?) one could also wrap the with statement inside a loop to get the break to work - though that would be semantically misleading. So while a working solution, probably not something that would be recommend).

    0 讨论(0)
  • 2020-12-02 11:32

    You could put everything inside a function, and when the condition is true call a return.

    0 讨论(0)
  • 2020-12-02 11:32

    Change from "break" to "f.close"

    with open(path) as f:
        print('before condition')
        if <condition>: f.close()
        print('after condition')
    
    0 讨论(0)
  • 2020-12-02 11:33

    The best way would be to encapsulate it in a function and use return:

    def do_it():
        with open(path) as f:
            print 'before condition'
            if <condition>:
                return
            print 'after condition'
    
    0 讨论(0)
  • 2020-12-02 11:38

    There exists a function __exit__() for this purpose. Syntax is as follows:

    with VAR = EXPR:
      try:
        BLOCK
      finally:
        VAR.__exit__()
    
    0 讨论(0)
  • with giving you trouble? Throw more with-able objects at the problem!

    class fragile(object):
        class Break(Exception):
          """Break out of the with statement"""
    
        def __init__(self, value):
            self.value = value
    
        def __enter__(self):
            return self.value.__enter__()
    
        def __exit__(self, etype, value, traceback):
            error = self.value.__exit__(etype, value, traceback)
            if etype == self.Break:
                return True
            return error
    

    Just wrap the expression you're going to with with fragile, and raise fragile.Break to break out at any point!

    with fragile(open(path)) as f:
        print 'before condition'
        if condition:
            raise fragile.Break
        print 'after condition'
    

    Benefits of this setup

    • Uses with and just the with; doesn't wrap your function in a semantically misleading one-run 'loop' or a narrowly specialized function, and doesn't force you to do any extra error handling after the with.
    • Keeps your local variables available, instead of having to pass them to a wrapping function.
    • Nestable!

      with fragile(open(path1)) as f:
          with fragile(open(path2)) as g:
              print f.read()
              print g.read()
              raise fragile.Break
              print "This wont happen"
          print "This will though!"
      

      This way, you don't have to create a new function to wrap the outer with if you want both to break.

    • Doesn't require restructuring at all: just wrap what you already have with fragile and you're good to go!

    Downsides of this setup

    • Doesn't actually use a 'break' statement. Can't win em all ;)
    0 讨论(0)
提交回复
热议问题