2012-02-13 11 views
5

के साथ एक बच्चे धागे में पाइथन raw_input() को बाधित करना एक बहुप्रचारित पायथन प्रोग्राम में, एक थ्रेड कभी-कभी निर्मित raw_input() का उपयोग करके कंसोल इनपुट मांगता है। मैं शैल पर इनपुट सी (यानी, एक सिगिनट सिग्नल के साथ) टाइप करके कच्चे_इनपुट प्रॉम्प्ट पर प्रोग्राम को बंद करने में सक्षम होना चाहता हूं। हालांकि, जब बच्चा धागा raw_input निष्पादित कर रहा है, टाइपिंग^सी कुछ भी नहीं करता है - कीबोर्ड इंटरप्ट को तब तक नहीं उठाया जाता जब तक कि मैं वापसी नहीं करता (raw_input छोड़कर)।^सी/कीबोर्ड इंटरप्ट

उदाहरण के लिए, निम्नलिखित कार्यक्रम में:

import threading 

class T(threading.Thread): 
    def run(self): 
     x = raw_input() 
     print x 

if __name__ == '__main__': 
    t = T() 
    t.start() 
    t.join() 

टंकण^सी जब तक के बाद इनपुट समाप्त हो गया है कुछ नहीं करता है। हालांकि, अगर हम केवल T().run() (यानी, सिंगल थ्रेडेड केस: केवल मुख्य थ्रेड में raw_input चलाएं) पर कॉल करें,^सी तुरंत प्रोग्राम बंद कर देता है।

संभवतः, ऐसा इसलिए है क्योंकि SIGINT को मुख्य थ्रेड पर भेजा जाता है, जिसे निलंबित कर दिया जाता है (जीआईएल की प्रतीक्षा) जबकि कंसोल पर फोर्कड थ्रेड ब्लॉक पढ़ते हैं। कच्चे_इनपुट रिटर्न के बाद जीआईएल को पकड़ने तक मुख्य धागा अपने सिग्नल हैंडलर को निष्पादित नहीं करता है। (अगर मैं इस बारे में गलत हूं तो कृपया मुझे सही करें - मैं पाइथन के थ्रेडिंग कार्यान्वयन पर एक विशेषज्ञ नहीं हूं।)

क्या एसआईजीआईएनटी को संभालने की इजाजत देते हुए कच्चे_इनपूट की तरह stdin से पढ़ने का कोई तरीका है मुख्य धागे से और इस प्रकार पूरी प्रक्रिया को नीचे लाते हैं?

[मैं मैक ओएस एक्स और कुछ अलग Linuxes पर ऊपर व्यवहार मनाया गया है।]


संपादित करें: मैं ऊपर मूल समस्या mischaracterized गए हैं। आगे की जांच पर, यह मुख्य थ्रेड का कॉल join() है जो सिग्नल हैंडलिंग को रोक रहा है: Guido van Rossum ने स्वयं को बताया है कि the underlying lock acquire in join is uninterruptible। इसका मतलब यह है कि सिग्नल वास्तव में पूरे धागे को समाप्त होने तक स्थगित कर दिया जाता है - इसलिए इसका वास्तव में raw_input के साथ कुछ भी नहीं है (केवल तथ्य यह है कि पृष्ठभूमि धागा अवरुद्ध हो रहा है ताकि जॉइन पूरा न हो)।

+3

एक बस धागे और व्यवधान गठबंधन नहीं करता है ... [boromir.jpg] – JBernardo

उत्तर

0

इस अवधि के दौरान वास्तव में कोई आसान तरीका नहीं है।

एक दृष्टिकोण आपके कोड को फिर से व्यवस्थित करना और तोड़ना है कि Ctrl-C की आवश्यकता वाले कार्यों के कुछ हिस्सों को मुख्य थ्रेड पर निष्पादित किया जाता है। आप परिणाम मूल्यों के लिए निष्पादन अनुरोध भेजने के लिए कतारों का उपयोग करते हैं। आपको मुख्य धागे के लिए एक इनपुट कतार की आवश्यकता होती है, और प्रति आउटपुट कतार प्रति गैर-मुख्य धागे की आवश्यकता होती है; और एक समन्वित मुख्य धागा निकास। जाहिर है, इस तरह किसी भी समय किसी एक ब्लॉकिंग फ़ंक्शन को निष्पादित किया जाता है, जो कि आप जो चाहते हैं वह नहीं हो सकता है।

Here's a working example of this idea समेकित मुख्य थ्रेड निकास के लिए सेमफोरों के थोड़ा विपरीत उपयोग के साथ।

3

जब कोई टाइमआउट नहीं कहा जाता है, तो यह निर्बाध है, लेकिन जब इसे टाइमआउट के साथ बुलाया जाता है, तो यह बाधित होता है। एक मनमाना टाइमआउट जोड़ने और थोड़ी देर के पाश में डालने का प्रयास करें:

while my_thread.isAlive(): 
    my_thread.join(5.0) 
संबंधित मुद्दे