Ctrl-C के साथ पायथन स्क्रिप्ट को नहीं मार सकता


117

मैं निम्नलिखित स्क्रिप्ट के साथ पायथन थ्रेडिंग का परीक्षण कर रहा हूं:

import threading

class FirstThread (threading.Thread):
    def run (self):
        while True:
            print 'first'

class SecondThread (threading.Thread):
    def run (self):
        while True:
            print 'second'

FirstThread().start()
SecondThread().start()

यह कुबंटु 11.10 पर पायथन 2.7 में चल रहा है। Ctrl+ Cइसे नहीं मारेंगे। मैंने सिस्टम सिग्नल के लिए एक हैंडलर जोड़ने की भी कोशिश की, लेकिन इससे कोई फायदा नहीं हुआ:

import signal 
import sys
def signal_handler(signal, frame):
    sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)

प्रोग्राम को पृष्ठभूमि के साथ भेजने के बाद मैं इसे पीआईडी ​​द्वारा मार रहा हूं Ctrl+ Z, जिसे अनदेखा नहीं किया जा रहा है। Ctrl+ क्यों Cलगातार इतनी अनदेखी की जा रही है? मैं इसे कैसे हल करूं?


@dotancohen क्या यह विंडोज पर काम कर रहा है?
kiriloff

@vitaibian: मैंने विंडोज पर परीक्षण नहीं किया है, लेकिन यह गैर-ओएस विशिष्ट लगता है।
11:anc पर dotancohen

जवाबों:


178

Ctrl+ Cमुख्य धागे को समाप्त करता है, लेकिन क्योंकि आपके धागे डेमॉन मोड में नहीं हैं, वे चलते रहते हैं, और इससे प्रक्रिया जीवित रहती है। हम उन्हें डेमॉन बना सकते हैं:

f = FirstThread()
f.daemon = True
f.start()
s = SecondThread()
s.daemon = True
s.start()

लेकिन फिर एक और समस्या है - एक बार जब मुख्य सूत्र ने आपके धागे शुरू कर दिए हैं, तो इसके लिए कुछ और नहीं है। तो यह बाहर निकलता है, और धागे तुरंत नष्ट हो जाते हैं। तो चलिए मुख्य सूत्र को जीवित रखते हैं:

import time
while True:
    time.sleep(1)

अब यह प्रिंट 'पहली' रखेंगे और 'दूसरा' जब तक आप हिट Ctrl+ C

संपादित करें: जैसा कि टिप्पणीकारों ने बताया है, डेमन थ्रेड्स को अस्थायी फ़ाइलों जैसी चीजों को साफ करने का मौका नहीं मिल सकता है। यदि आपको इसकी आवश्यकता है, तो KeyboardInterruptमुख्य धागे को पकड़ें और इसे क्लीनअप और शटडाउन को समेटें। लेकिन कई मामलों में, डेमन थ्रेड्स को अचानक मरने देना शायद काफी अच्छा है।


6
आपको यह उल्लेख करना चाहिए कि ऐसा करने से थ्रेड्स को इनायत से नहीं रोका जाता है और कुछ संसाधनों को जारी नहीं किया जाता है।
टॉमसो बारबुगली

1
खैर, Ctrl-C कुछ भी रोकने का एक सुंदर तरीका नहीं है। मुझे यकीन नहीं है कि क्या संसाधन छोड़ दिए जाएंगे - क्या प्रक्रिया से बाहर निकलने पर ओएस को कुछ भी पुनः प्राप्त नहीं करना चाहिए?
थॉमस के

7
@ThomasK द्वारा बनाई गई अस्थायी फाइलें tempfile.TemporaryFile()उदाहरण के लिए, डिस्क पर छोड़ी जा सकती हैं।
Feermermmel

1
@ deed02392: मुझे नहीं पता कि मुख्य धागे का वास्तव में क्या होता है, लेकिन जहां तक ​​मुझे पता है कि बाहर निकलने के बाद आप इसके साथ कुछ नहीं कर सकते। जब सभी गैर-डेमन धागे समाप्त हो जाएंगे तो प्रक्रिया समाप्त हो जाएगी; माता-पिता-बच्चे के रिश्ते उस में नहीं आते हैं।
थॉमस के

4
जैसे python3 में दिखता है आप पास कर सकते हैंdaemon=True करने के लिएThread.__init__
रयान हेनिंग


3

मुझे लगता है कि जब आप उन्हें मरने की उम्मीद करते हैं तो अपने थ्रेड्स पर जॉइन () कॉल करना सबसे अच्छा है। मैंने छोरों को समाप्त करने के लिए आपके कोड के साथ कुछ स्वतंत्रता ली है (आप वहां भी जो भी सफाई की आवश्यकता है उसे जोड़ सकते हैं)। वेरिएबल डाई को प्रत्येक पास पर सत्य के लिए जांचा जाता है और जब यह सत्य होता है तब प्रोग्राम से बाहर निकलता है।

import threading
import time

class MyThread (threading.Thread):
    die = False
    def __init__(self, name):
        threading.Thread.__init__(self)
        self.name = name

    def run (self):
        while not self.die:
            time.sleep(1)
            print (self.name)

    def join(self):
        self.die = True
        super().join()

if __name__ == '__main__':
    f = MyThread('first')
    f.start()
    s = MyThread('second')
    s.start()
    try:
        while True:
            time.sleep(2)
    except KeyboardInterrupt:
        f.join()
        s.join()

while Trueमूर्खतापूर्ण है, आपको joinसीधे-सीधे कहना चाहिए और यह ओवरराइड फ़ंक्शन एक प्रकार का संदिग्ध है। हो सकता है कि def join(self, force=False): if force: self.die = Trueइतना है कि join()द्वारा अपरिवर्तित है join(force=True)उन्हें मारता। लेकिन फिर भी, दोनों में से किसी एक में शामिल होने से पहले सूचित करना बेहतर है ।
o11c

0

@Thomas K के उत्तर का एक उन्नत संस्करण:

  • इस जिस्ट केis_any_thread_alive() अनुसार एक सहायक फ़ंक्शन को परिभाषित करना , जो स्वचालित रूप से समाप्त हो सकता है।main()

उदाहरण कोड:

import threading

def job1():
    ...

def job2():
    ...

def is_any_thread_alive(threads):
    return True in [t.is_alive() for t in threads]

if __name__ == "__main__":
    ...
    t1 = threading.Thread(target=job1,daemon=True)
    t2 = threading.Thread(target=job2,daemon=True)
    t1.start()
    t2.start()

    while is_any_thread_alive([t1,t2]):
        time.sleep(0)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.