2012-03-24 3 views
9

저는 파이썬과 저주로 조금 놀고 있습니다.Python curses 딜레마

나는 모든 것이 잘 밖으로 작동하므로 통해, curses.endwin()가 호출되는 모든 방법을 기다리면 내가

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() 

를 실행합니다. 그러나 Ctrl-C로 짧게 자르면 curses.endwin()이 호출되지 않으므로 터미널 세션이 엉망이됩니다.

이 상황을 처리하는 적절한 방법은 무엇입니까? 프로그램 종료 (예 : Ctrl-C, Ctrl-Z)에 관계없이 프로그램을 종료/중단하려고해도 터미널이 엉망이되지 않도록하려면 어떻게해야합니까?

답변

8

이 작업을 수행 할 수 있습니다 :

def main(): 
    curses.initscr() 

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

또는 더 좋게, 컨텍스트 래퍼합니다

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

을 할 수 있습니다 :

  • 을 통해 curses.endwin()
  • 캡처 인터럽트 신호를 특별히 호출하는 try/finally 블록에 코드를 포장 signal 라이브러리
  • atexit 라이브러리를 사용하십시오.

첫 번째 옵션은 많은 경우 (코드를 많이 실행하지 않는 경우) 가장 간단한 경우입니다.

Ctrl + C에 대해 특별을 수행하려는 경우 두 번째 옵션이 가장 구체적입니다.

마지막 옵션은 프로그램 종료와 상관없이 항상 특정 종료 작업을 수행하려는 경우 가장 강력합니다.

+0

는'finally'보다는'atexit' 정말 더 강력 :

여러분의 프로그램은 예를 들어, 래퍼에 대한 함수로 간다? – asmeurer

+0

@asmeurer'finally' 버전의 문제는 모든 프로그램 코드가'try' 블록 내에 있음을 보장해야한다는 것입니다. 말하자면 다중 스레드 환경에서는 반드시 그런 것은 아닙니다. – Amber

1

내 충고 : 테스트 목적으로 간단한 래퍼 셸 스크립트를 사용하여 스크립트를 호출하십시오. 쉘 스크립트가 사용 가능한 상태로 다시 터미널 설정을 가져올 수있는 reset 명령을 수행 있습니다

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

이 ... run.sh으로 그에게 전화 행복합니다. 이 명령은 인수를 명령으로 입력하면 쉘을 거의 정확하게 실행해야합니다 (더 정확하게는 인수를 하드 인용으로 감싸는 경우).

는 최고 수준의 진입 점을 프로그램이 포착되지 않은 예외 이상 종단의 얼굴에, 강력한 상태로 터미널을 떠날 수 있도록 ... 중 하나를 호출 할 curses.wrapper() 방법을 사용하십시오 (아마도 main() 또는 무엇이든 main_curses_ui() 당신에게 구현하기로 선택하거나 커서 가시성을 복원하고 "cbreak"(정식/조리 입력) 모드를 복원하고 정상적인 "에코"설정을 복원하고 다른 어떤 것도 해치울 수있는 curses.* 방법 순으로 코드를 래핑하십시오.

Python: atexit Handlers을 사용하여 모든 정리 작업을 등록 할 수도 있습니다. 그러나 코드가 호출되지 않는 경우가있을 수 있습니다. 어떤 종류의 잡히지 않는 신호 및 os._exit()이 호출되는 상황이있을 수 있습니다.

내 작은 쉘 스크립트 래퍼는 이러한 경우에도 상당히 견고해야합니다. 내가 당신을 믿지

44

참조 curses.wrapper 를 찾고 있습니다 http://docs.python.org/dev/library/curses.html#curses.wrapper

그것은 (1) 초기화에 curses.cbreak(), curses.noecho()와 curses_screen.keypad을 종료 그들을 반대합니다

,도 이탈이 예외 인 경우

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

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

이 대답을 받아 들여야합니다. –