with while open manager español else decorators context python with-statement

while - with python español



¿Romper o salir de la declaración “con”? (9)

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

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

Solo me gustaría salir de una declaración con ciertas condiciones:

with open(path) as f: print ''before condition'' if <condition>: 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 <condition>: print ''after condition'' , ¿es como se muestra arriba?)


Esta es una pregunta antigua, pero esta es una aplicación para el modesto lenguaje de "alcance rompible". Acabo de incrustar su declaración en el interior:

for _ in (True,): with open(path) as f: print ''before condition'' if <condition>: 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.


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

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


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 <condition>: return print ''after condition''


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


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 programa - probablemente no ideal)
  • excepción (generar excepción dentro de "con", captura abajo)

Tener una función y usar return es probablemente la solución más limpia y fácil 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 resto 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).


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


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 estallar 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 de errores adicional 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 declaración de ''ruptura''. No puedo ganarlos todos;)

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