2012-03-24 7 views
9

मैं पाइथन और शाप के साथ थोड़ा सा खेल रहा हूं।पायथन शाप दुविधा

जब मैं

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

चलाने अगर मैं सभी तरह के माध्यम से, curses.endwin() कहा जाता हो जाता है तो सब कुछ ठीक से काम करता है प्रतीक्षा करें। हालांकि, अगर मैं इसे 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") 
-1

आप संकेत को पकड़ने और कब्जे के दौरान endwin() चलाने की जरूरत है।

इस पर जानकारी के लिए, इसे देखो तो जवाब: How do I capture SIGINT in Python?

0

आप कर सकते हैं:

  • कि curses.endwin()
  • कब्जा बाधा संकेत के माध्यम से विशेष रूप से कहता है एक try/finally ब्लॉक में अपने कोड लपेट signal लाइब्रेरी
  • atexit लाइब्रेरी का उपयोग करें।

पहला विकल्प शायद मूलभूत मामले के लिए सबसे सरल है (यदि आप अधिक कोड नहीं चला रहे हैं)।

दूसरा विकल्प सबसे विशिष्ट है, यदि आप Ctrl + C के लिए विशेष कुछ करना चाहते हैं।

अंतिम विकल्प सबसे मजबूत है यदि आप हमेशा कुछ शट डाउन कार्य करना चाहते हैं, भले ही आपका प्रोग्राम समाप्त हो रहा हो।

+0

'atexit' वास्तव में अधिक' finally' से मजबूत है? – asmeurer

+0

@asmeurer यह 'आखिरकार' संस्करण की बात है, आपको यह गारंटी देने की आवश्यकता है कि आपका सभी प्रोग्राम कोड 'try' block के भीतर है। कहें, एक बहुप्रचारित वातावरण, यह आवश्यक नहीं है। – Amber

1

मेरी सलाह: परीक्षण उद्देश्यों के लिए, एक साधारण रैपर शैल स्क्रिप्ट का उपयोग करके अपनी स्क्रिप्ट को कॉल करें; खोल स्क्रिप्ट एक reset आदेश प्रदर्शन अपने टर्मिनल सेटिंग्स एक प्रयोग करने योग्य स्थिति में वापस लाना होगा:

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

... फोन कि run.sh के रूप में और खुश हो। यह आपके आदेश को लगभग ठीक उसी तरह चलाएगा जैसे आपका खोल होगा यदि आपने कमांड के रूप में तर्क दर्ज किया है (अधिक सटीक यदि आप हार्ड कोट्स में तर्क लपेटते हैं)।

यह सुनिश्चित करने के अपने कार्यक्रम ध्यान में न आया अपवाद और असामान्य समाप्ति का सामना करने में एक मजबूत स्थिति में टर्मिनल छोड़ देंगे, ... या तो कॉल करने के लिए curses.wrapper() विधि का उपयोग अपने शीर्ष स्तर प्रवेश बिंदु (शायद main() या जो भी आप main_curses_ui() लागू करने के लिए चुनें) या कर्सर दृश्यता बहाल करने के लिए curses.* विधियों के अपने अनुक्रम में अपना कोड लपेटें, "क्रैब" (कैनोलिक/पकाया इनपुट) मोड को पुनर्स्थापित करें, सामान्य "गूंज" सेटिंग्स को पुनर्स्थापित करें और जो कुछ भी आप के साथ मिल सकते हैं उसे पुनर्स्थापित करें।

आप अपने सभी क्लीन-अप कार्यों को पंजीकृत करने के लिए Python: atexit Handlers का भी उपयोग कर सकते हैं। लेकिन ऐसे मामले भी हो सकते हैं जहां आपका कोड नहीं कहा जाता है --- कुछ प्रकार के गैर-पकड़ने योग्य सिग्नल और किसी भी स्थिति जहां os._exit() आवेदित है।

मेरी छोटी शेल स्क्रिप्ट रैपर उन मामलों में भी काफी मजबूत होना चाहिए।

44

मैं आपको लगता है कि curses.wrapper के लिए देख रहे देखें http://docs.python.org/dev/library/curses.html#curses.wrapper

यह (1) init पर 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

यह स्वीकार्य उत्तर होना चाहिए। –

संबंधित मुद्दे