2012-03-24 25 views
9

Estoy jugando un poco con Python y maldiciones.Python maldice el dilema

Cuando corro

import time 
import curses 

def main(): 
    curses.initscr() 
    curses.cbreak() 
    for i in range(3): 
     time.sleep(1) 
     curses.flash() 
     pass 
    print("Hello World") 
    curses.endwin() 

if __name__ == '__main__': 
    main() 

si espero hasta el final, curses.endwin() es llamado así que todo funciona bien. Sin embargo, si lo corto con Ctrl-C, nunca se llama a curses.endwin(), así que daña la sesión de mi terminal.

¿Cuál es la forma correcta de manejar esta situación? ¿Cómo puedo asegurarme de que no importa cómo intente finalizar/interrumpir el programa (por ejemplo, Ctrl-C, Ctrl-Z), no dañe la terminal?

Respuesta

8

Usted puede hacer esto:

def main(): 
    curses.initscr() 

    try: 
     curses.cbreak() 
     for i in range(3): 
      time.sleep(1) 
      curses.flash() 
      pass 
     print("Hello World") 
    finally: 
     curses.endwin() 

O más bien, hacer un contenedor de contexto:

class CursesWindow(object): 
    def __enter__(self): 
     curses.initscr() 

    def __exit__(self): 
     curses.endwin() 

def main(): 
    with CursesWindow(): 
     curses.cbreak() 
     for i in range(3): 
      time.sleep(1) 
      curses.flash() 
      pass 
     print("Hello World") 
0

Puede:

  • envolver su código en un bloque try/finally que llama curses.endwin()
  • captura de la señal de interrupción en concreto a través de la biblioteca signal
  • usa la biblioteca atexit.

La primera opción es probablemente la más simple para un caso básico (si no está ejecutando mucho código).

La segunda opción es la más específica, si desea hacer algo especial para Ctrl + C.

La última opción es la más robusta si siempre quiere hacer ciertas acciones de apagado, sin importar cómo termine su programa.

+0

es 'atexit' realmente más robusto que' finally'? – asmeurer

+0

@asmeurer Es más una cuestión de la versión 'finalmente' requiere que garantices que todo tu código de programa está dentro del bloque 'try'. En, digamos, un entorno multiproceso, ese no es necesariamente el caso. – Amber

1

Mi consejo: Para fines de prueba, llame a su secuencia de comandos mediante un simple script shell wrapper; tiene la secuencia de comandos shell ejecutar un comando reset para llevar la configuración del terminal en un estado utilizable:

#!/bin/sh 
eval "[email protected]" 
stty -sane 
reset 

... llamada que como run.sh y ser feliz. Esto debería ejecutar su comando casi exactamente como lo haría su caparazón si usted ingresara los argumentos como un comando (más exactamente si ajusta los argumentos en comillas).

Para garantizar que el programa saldrá de la terminal en un estado sólido, en el frente de excepciones no capturadas y terminaciones anormales ... O bien utilizar el método curses.wrapper() para llamar a su punto de entrada de nivel superior (probablemente main() o lo que main_curses_ui() elija implementar) o envuelva su código en su propia secuencia de métodos curses.* para restaurar la visibilidad del cursor, restaurar el modo de "interrupción" (entrada canónica/cocinada), restablecer la configuración normal de "eco" y cualquier otra cosa que pueda haber robado.

También puede usar el Python: atexit Handlers para registrar todas sus acciones de limpieza. Pero aún puede haber casos en los que su código no se llame, algunos tipos de señales no detectables y cualquier situación en la que se invoque os._exit().

Mi pequeño contenedor de scripts de shell debe ser bastante robusto incluso en esos casos.

44

Te creo están buscando curses.wrapper Ver http://docs.python.org/dev/library/curses.html#curses.wrapper

Lo hará curses.cbreak(), curses.noecho() y curses_screen.keypad (1) el inicio y revertirlas en la salida, incluso si la salida fue una excepción.

Su programa va en función a la envoltura, ejemplo:

def main(screen): 
    """screen is a curses screen passed from the wrapper""" 
    ... 

if __name__ == '__main__': 
    curses.wrapper(main) 
+4

esta debería ser la respuesta aceptada. –

Cuestiones relacionadas