¿Romper o salir de la statement “con”?

Solo me gustaría salir de una statement con ciertas condiciones:

 with open(path) as f: print 'before condition' if : break #syntax error! print 'after condition' 

Por supuesto, lo anterior no funciona. ¿Hay alguna forma de hacer esto? (Sé que puedo invertir la condición: if not : print 'after condition' , ¿es como se muestra arriba?)

La mejor manera sería encapsularlo en una función y usar el return :

 def do_it(): with open(path) as f: print 'before condition' if : return print 'after condition' 

with darte problemas? ¡Lanza más objetos con el problema!

 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 

Simplemente envuelva la expresión con la que va a raise fragile.Break con fragile , y raise fragile.Break fragile . ¡ raise fragile.Break para escapar en cualquier momento!

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

Beneficios de esta configuración.

  • Utiliza with y solo el with ; no envuelve su función en un ‘bucle’ de una ejecución semánticamente engañoso o en una función estrechamente especializada, y no lo obliga a realizar ningún manejo adicional de errores después de with .
  • Mantiene sus variables locales disponibles, en lugar de tener que pasarlas a una función de ajuste.
  • Anidables

     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!" 

    De esta manera, no tiene que crear una nueva función para envolver el exterior with si desea que ambos se rompan.

  • No requiere reestructuración en absoluto: ¡simplemente envuelva lo que ya tiene con fragile y listo!

Desventajas de esta configuración

  • En realidad no usa una statement de ‘ruptura’. No puedo ganarlos todos;)

Creo que deberías simplemente reestructurar la lógica:

 with open(path) as f: print 'before condition checked' if not : print 'after condition checked' 

Ya que la break solo puede ocurrir dentro de un bucle, sus opciones son algo limitadas dentro de with :

  • return (poner “con” + instrucciones asociadas dentro de la función)
  • salida (fianza del progtwig – probablemente no ideal)
  • excepción (generar excepción dentro de “con”, captura abajo)

Tener una función y usar el return es probablemente la solución más limpia y más fácil aquí si puede aislar las declaraciones with y las declaraciones asociadas (y nada más) dentro de una función.

De lo contrario, genere una excepción dentro de with cuando sea necesario, atrape inmediatamente debajo / fuera de with para continuar con el rest del código.

Actualización : como sugiere OP en los comentarios a continuación (¿quizás un poco de nudo en la mejilla?), También se podría ajustar la instrucción with dentro de un bucle para hacer que la break funcione, aunque eso sería semánticamente engañoso. Entonces, si bien una solución de trabajo, probablemente no sea algo que se recomiende).

 f = open("somefile","r") for line in f.readlines(): if somecondition: break; f.close() 

No creo que puedas romper con el … necesitas usar un bucle …

[editar] o simplemente hacer el método de función que otros mencionan

Esta es una pregunta antigua, pero esta es una aplicación para el modesto lenguaje de “scope rompible”. Acabo de incrustar su statement en el interior:

 for _ in (True,): with open(path) as f: print 'before condition' if : break print 'after condition' 

Este idioma crea un “bucle”, que siempre se ejecuta exactamente una vez, con el único propósito de encerrar un bloque de código dentro de un ámbito que puede romperse condicionalmente. En el caso de OP, fue una invocación del administrador de contexto que se adjuntaría, pero podría ser cualquier secuencia limitada de declaraciones que puedan requerir un escape condicional.

La respuesta aceptada está bien, pero esta técnica hace lo mismo sin necesidad de crear una función, que no siempre es conveniente o deseada.

Podría poner todo dentro de una función, y cuando la condición sea verdadera, llame a una devolución.

como fragmento de taquigrafía:

 class a: def __enter__(self): print 'enter' def __exit__(self ,type, value, traceback): print 'exit' for i in [1]: with a(): print("before") break print("after") 

 enter before exit 

Existe una función __exit__() para este propósito. La syntax es la siguiente:

 with VAR = EXPR: try: BLOCK finally: VAR.__exit__()