সিটিটিএল-সি দিয়ে পাইথন স্ক্রিপ্টটি মেরে ফেলা যায় না


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

এটি কুবুন্টু ১১.১০ তে পাইথন ২. 2. এ চলছে। 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

উত্তর:


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এটির প্রয়োজন হয়, তবে মূল থ্রেডটি ধরুন এবং এটি পরিষ্কার-পরিচ্ছন্নতা এবং শাটডাউন সমন্বিত করুন। তবে অনেক ক্ষেত্রেই হঠাৎ ডেমন থ্রেড মারা যাওয়া সম্ভবত যথেষ্ট ভাল good


6
আপনার উল্লেখ করা উচিত যে এই থ্রেডগুলি করুণার সাথে বন্ধ করা যায় না এবং কিছু সংস্থান প্রকাশ করা হয় না।
টমমাসো বার্বুগলি

1
ওয়েল, Ctrl-C কখনও কোনও কিছু থামানোর এক দৃষ্টিনন্দন উপায় নয়। আমি নিশ্চিত নই যে কোন সংস্থানগুলি ছেড়ে যাবে - প্রক্রিয়াটি শেষ হয়ে গেলে ওএসকে কিছু দাবি করা উচিত নয়?
থমাস কে

7
@ থমাসক দ্বারা নির্মিত অস্থায়ী ফাইলগুলি tempfile.TemporaryFile()সম্ভবত ডিস্কে রেখে যেতে পারে।
ফিউমার্মেলেল

1
@ ডিড02392: মূল থ্রেডের ঠিক কী ঘটেছিল তা আমি ঠিক জানি না তবে যতদূর আমি জানি যে এটি বেরিয়ে যাওয়ার পরে আপনি এটি দিয়ে কিছুই করতে পারবেন না। সমস্ত নন-ডেমন থ্রেড শেষ হয়ে গেলে প্রক্রিয়াটি শেষ হবে; পিতা-মাতার সন্তানের সম্পর্ক এর মধ্যে আসে না।
টমাস কে

4
অজগর 3 এ দেখে মনে হচ্ছে আপনি যেতেdaemon=True পারেনThread.__init__
রায়ান হেইনিং

8

কীবোর্ড ইন্টারটারপেট এবং সিগন্যালগুলি কেবল প্রক্রিয়া (যেমন মূল থ্রেড) দ্বারা দেখা যায় ... সিটিআরএল-সি দেখুন বা পাইথনটিতে থ্রেডগুলি মেরে ফেলার জন্য কীবোর্ড ইন্টারটারপেট


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

@ থমাস কে এর উত্তরের একটি উন্নত সংস্করণ:

  • এই গিস্টis_any_thread_alive() অনুসারে একটি সহায়ক ফাংশন সংজ্ঞা দেওয়া , যা স্বয়ংক্রিয়ভাবে শেষ হতে পারে terminmain()

উদাহরণ কোডগুলি:

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)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.