কোনও থ্রেড মারার কোনও উপায় আছে কি?


764

কোনও পতাকা / সেমোফোরস / ইত্যাদি সেট না করে / পরীক্ষা করেই চলমান থ্রেডটি শেষ করা সম্ভব?

উত্তর:


672

পাইথন এবং যে কোনও ভাষায় হঠাৎ করে কোনও থ্রেড মেরে ফেলা খুব খারাপ প্যাটার্ন। নিম্নলিখিত বিষয়গুলি চিন্তা করুন:

  • থ্রেডটিতে একটি সমালোচনা সংস্থান রয়েছে যা সঠিকভাবে বন্ধ করা উচিত
  • থ্রেডটি আরও বেশ কয়েকটি থ্রেড তৈরি করেছে যা অবশ্যই হত্যা করতে হবে।

আপনি যদি এটি সামর্থ্য করতে পারেন তবে এটি পরিচালনা করার দুর্দান্ত উপায়টি (যদি আপনি নিজের থ্রেডগুলি পরিচালনা করে থাকেন) হ'ল একটি প্রস্থান_প্রকাশের পতাকাটি যা প্রতিটি থ্রেডগুলি নিয়মিত বিরতিতে পরীক্ষা করে দেখবে যে এটি বেরোনোর ​​সময় এসেছে কিনা।

উদাহরণ স্বরূপ:

import threading

class StoppableThread(threading.Thread):
    """Thread class with a stop() method. The thread itself has to check
    regularly for the stopped() condition."""

    def __init__(self,  *args, **kwargs):
        super(StoppableThread, self).__init__(*args, **kwargs)
        self._stop_event = threading.Event()

    def stop(self):
        self._stop_event.set()

    def stopped(self):
        return self._stop_event.is_set()

এই stop()কোডটিতে, থ্রেডটি প্রস্থান করতে চাইলে আপনাকে কল করা উচিত , এবং থ্রেডটি সঠিকভাবে ব্যবহারের জন্য অপেক্ষা করা উচিতjoin() । থ্রেডটি নিয়মিত বিরতিতে স্টপ ফ্ল্যাগটি পরীক্ষা করা উচিত।

কিছু ক্ষেত্রে আছে যখন আপনার সত্যিই একটি থ্রেড মারতে হবে। একটি উদাহরণ হ'ল যখন আপনি কোনও বহিরাগত লাইব্রেরিটি মুড়ে রাখছেন যা দীর্ঘ কলগুলির জন্য ব্যস্ত এবং আপনি এটিকে বাধা দিতে চান।

নিম্নলিখিত কোডটি পাইথন থ্রেডে কিছু ব্যতিক্রম বাড়াতে (কিছু সীমাবদ্ধতা সহ) অনুমতি দেয়:

def _async_raise(tid, exctype):
    '''Raises an exception in the threads with id tid'''
    if not inspect.isclass(exctype):
        raise TypeError("Only types can be raised (not instances)")
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid),
                                                     ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # "if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"
        ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), None)
        raise SystemError("PyThreadState_SetAsyncExc failed")

class ThreadWithExc(threading.Thread):
    '''A thread class that supports raising exception in the thread from
       another thread.
    '''
    def _get_my_tid(self):
        """determines this (self's) thread id

        CAREFUL : this function is executed in the context of the caller
        thread, to get the identity of the thread represented by this
        instance.
        """
        if not self.isAlive():
            raise threading.ThreadError("the thread is not active")

        # do we have it cached?
        if hasattr(self, "_thread_id"):
            return self._thread_id

        # no, look for it in the _active dict
        for tid, tobj in threading._active.items():
            if tobj is self:
                self._thread_id = tid
                return tid

        # TODO: in python 2.6, there's a simpler way to do : self.ident

        raise AssertionError("could not determine the thread's id")

    def raiseExc(self, exctype):
        """Raises the given exception type in the context of this thread.

        If the thread is busy in a system call (time.sleep(),
        socket.accept(), ...), the exception is simply ignored.

        If you are sure that your exception should terminate the thread,
        one way to ensure that it works is:

            t = ThreadWithExc( ... )
            ...
            t.raiseExc( SomeException )
            while t.isAlive():
                time.sleep( 0.1 )
                t.raiseExc( SomeException )

        If the exception is to be caught by the thread, you need a way to
        check that your thread has caught it.

        CAREFUL : this function is executed in the context of the
        caller thread, to raise an excpetion in the context of the
        thread represented by this instance.
        """
        _async_raise( self._get_my_tid(), exctype )

( টোমর ফিলিবা দ্বারা কিলযোগ্য থ্রেডের উপর ভিত্তি করে of এর ফেরতের মান সম্পর্কে উদ্ধৃতিটি পাইথনেরPyThreadState_SetAsyncExc একটি পুরানো সংস্করণ থেকে পাওয়া যায় ))

ডকুমেন্টেশনে উল্লিখিত হিসাবে, এটি কোনও ম্যাজিক বুলেট নয় কারণ থ্রেড পাইথন ইন্টারপ্রেটারের বাইরে ব্যস্ত থাকলে এটি বাধাকে ধরবে না।

এই কোডটির একটি ভাল ব্যবহারের প্যাটার্নটি হ'ল থ্রেডটিকে একটি নির্দিষ্ট ব্যতিক্রম ধরা এবং ক্লিনআপ করা। এইভাবে, আপনি কোনও কাজে বাধা দিতে পারেন এবং এখনও সঠিক পরিষ্কার-পরিচ্ছন্নতা রাখতে পারেন।


77
@ ব্লুবার্ড :৫: তদুপরি, আমি নিশ্চিত নই যে থ্রেডগুলি হঠাৎ করে হত্যা করা উচিত নয় "কারণ থ্রেডটিতে একটি সমালোচনামূলক সংস্থান থাকতে পারে যা সঠিকভাবে বন্ধ করা উচিত": এটি একটি মূল প্রোগ্রাম এবং মূল প্রোগ্রামগুলি থেকে সত্য ব্যবহারকারীর দ্বারা আকস্মিকভাবে হত্যা করা যেতে পারে (উদাহরণস্বরূপ ইউনিক্সে সিটিআরএল-সি) - যে ক্ষেত্রে তারা সম্ভাবনাটিকে যথাসম্ভব সুন্দরভাবে পরিচালনা করার চেষ্টা করে। সুতরাং, আমি থ্রেডগুলির সাথে বিশেষ কী তা দেখতে ব্যর্থ হয়েছি এবং কেন তাদের প্রধান প্রোগ্রামগুলির মতো একই চিকিত্সা গ্রহণ করা উচিত নয় (যথা তারা আকস্মিকভাবে হত্যা করা যেতে পারে)। :) আপনি এই বিস্তারিত বলতে পারেন?
এরিক হে লেবিগোট

18
@ ইওল: অন্যদিকে, থ্রেডের মালিকানাধীন সমস্ত সংস্থানগুলি যদি স্থানীয় সংস্থান (খোলা ফাইল, সকেট) হয় তবে প্রক্রিয়া পরিষ্কারের ক্ষেত্রে লিনাক্স যুক্তিসঙ্গতভাবে ভাল এবং এটি ফুটো হয় না। যদিও আমি সকেট ব্যবহার করে একটি সার্ভার তৈরি করেছি সেখানে আমার কেস ছিল এবং আমি যদি Ctrl-C এর সাথে নিষ্ঠুর বাধা সৃষ্টি করি, তবে আমি আর প্রোগ্রামটি আরম্ভ করতে পারি না কারণ এটি সকেটকে আবদ্ধ করতে পারে না। আমার 5 মিনিট অপেক্ষা করতে হবে। সঠিক সমাধানটি ছিল সিটিআরএল-সি ধরা এবং সাফ সকেট সংক্ষেপণ করা।
ফিলিপ এফ

10
@ ব্লুবার্ড 75: বিটিডাব্লু ত্রুটি SO_REUSEADDRএড়াতে আপনি সকেট বিকল্পটি ব্যবহার করতে পারেন Address already in use
মেসা

12
এই উত্তরটি সম্পর্কে নোট: আমাকে (py2.6) জন্য অন্তত, আমি পাস ছিল Noneপরিবর্তে 0জন্য res != 1কেস, এবং আমি কল করতে ছিল ctypes.c_long(tid)এবং পাস যে কোনো ctypes TID সরাসরি বদলে কাজ করে।
ওয়াল্ট ডাব্লু

21
এটি উল্লেখ করার মতো যে _স্টপটি ইতিমধ্যে পাইথন 3 থ্রেডিং লাইব্রেরিতে রয়েছে। যেমন, সম্ভবত একটি ভিন্ন ভেরিয়েবল ব্যবহার করুন অন্যথায় আপনি একটি ত্রুটি পাবেন।
মৃত্যুকালীন সময়

113

এটি করার জন্য কোনও অফিসিয়াল এপিআই নেই, না।

থ্রেড, যেমন pthread_kill, বা টার্মিনেটথ্রেডকে মেরে ফেলার জন্য আপনার প্ল্যাটফর্ম API ব্যবহার করা উচিত। আপনি যেমন এপিআই অ্যাক্সেস করতে পারেন উদাহরণস্বরূপ পাইথনউইন বা সিটাইপসের মাধ্যমে।

লক্ষ্য করুন যে এটি স্বভাবতই অনিরাপদ। এটি সম্ভবত সিদ্ধান্তহীন আবর্জনা (স্ট্যাক ফ্রেমের স্থানীয় ভেরিয়েবলগুলি যা আবর্জনা হয়ে ওঠে) ডেকে আনে এবং অচলাবস্থার কারণ হতে পারে, যদি থ্রেডটি মেরে ফেলা হয় তবে জিআইএল এটি মারা যাওয়ার সময় রয়েছে।


26
এটা তোলে করবে ডেডলক হতে যদি প্রশ্ন থ্রেড Gil ঝুলিতে।
ম্যাথিয়াস উরলিচস

94

একজন multiprocessing.Processকরতে পারেনp.terminate()

যে ক্ষেত্রে আমি কোনও থ্রেডটি মেরে ফেলতে চাই, তবে পতাকা / লক / সিগন্যাল / সেমোফোর / ইভেন্টগুলি / যাই হোক না কেন ব্যবহার করতে চাই না, আমি থ্রেডগুলি সম্পূর্ণ প্রস্ফুটিত প্রসেসে প্রচার করি। কোডের জন্য যা কেবল কয়েকটি থ্রেড ব্যবহার করে ওভারহেডটি খারাপ হয় না।

উদাহরণস্বরূপ, সহজেই সাহায্যকারী "থ্রেডগুলি" সমাপ্ত করতে কার্যকর হবে যা I / O ব্লকিং কার্যকর করে

রূপান্তর তুচ্ছ হল: সংশ্লিষ্ট কোড ইন সমস্ত প্রতিস্থাপন threading.Threadসঙ্গে multiprocessing.Processএবং সমস্ত queue.Queueসঙ্গে multiprocessing.Queueএবং প্রয়োজনীয় কল যোগ p.terminate()আপনার পিতা বা মাতা প্রক্রিয়া যার তার সন্তানকে হত্যা করতে চায়p

এর জন্য পাইথন ডকুমেন্টেশনmultiprocessing দেখুন ।


ধন্যবাদ। আমি multiprocessing.JoinableQueue সঙ্গে queue.Queue প্রতিস্থাপিত এবং এই উত্তরটি অনুসৃত: stackoverflow.com/a/11984760/911207
ডেভিড ব্রাউন

এই ইস্যুতে প্রচুর পৃষ্ঠা। এটি আমার মনে হয় অনেকের কাছেই এটি সুস্পষ্ট সমাধান বলে মনে হচ্ছে
জিওলিওরি

6
multiprocessingদুর্দান্ত, তবে সচেতন থাকুন যে নতুন প্রক্রিয়াটি যুক্তিযুক্ত pick সুতরাং আর্গুমেন্টগুলির মধ্যে একটি যদি বাছাইযোগ্য কিছু না (যেমন একটি logging.log) এটি ব্যবহার করা ভাল ধারণা নাও হতে পারে multiprocessing
লাইগার

1
multiprocessingউইন্ডোজে নতুন প্রক্রিয়াতে যুক্তিগুলি যুক্ত হয়েছে, তবে লিনাক্স সেগুলি অনুলিপি করার জন্য দৃking় ব্যবহার করে (পাইথন ৩.7, অন্যান্য সংস্করণগুলি নিশ্চিত করে না)। সুতরাং আপনি লিনাক্সে কাজ করে এমন কোডটি শেষ করবেন তবে উইন্ডোতে আচারের ত্রুটি বাড়িয়ে তুলবে।
nyanpasu64

multiprocessingলগিং সঙ্গে কৃপণ ব্যবসা। ব্যবহার করতে হবে QueueHandler( এই টিউটোরিয়ালটি দেখুন )। আমি এটা হার্ড উপায় শিখেছি।
ফানচেন বাও

74

আপনি যদি পুরো প্রোগ্রামটি শেষ করার চেষ্টা করছেন তবে আপনি থ্রেডটিকে "ডিমন" হিসাবে সেট করতে পারেন। দেখুন Thread.daemon


এটি কোনও অর্থবোধ করে না। ডকুমেন্টেশনে স্পষ্টভাবে বলা হয়েছে, "শুরু () বলা হওয়ার আগে এটি অবশ্যই সেট করতে হবে, অন্যথায় রানটাইমআরার উত্থাপিত হবে না।" সুতরাং, আমি যদি এমন কোনও থ্রেডটি হত্যা করতে চাই যা মূলত ডেমন নয়, আমি কীভাবে এটি ব্যবহার করতে পারি?
রাফি খ্যাচাডৌড়িয়ান

27
রাফি আমি মনে করি তিনি প্রস্তাব দিচ্ছেন আপনি এটি আগে থেকেই সেট করে দেবেন, জেনেও যে আপনার মূল থ্রেডটি যখন প্রস্থান করে আপনিও ডিমন থ্রেডগুলি প্রস্থান করতে চান।
চমত্কার

1
নিশ্চিত নয় কেন এটি গৃহীত উত্তর নয়
এরিক

আপনার মূল প্রোগ্রামটি বন্ধ হয়ে গেলেও আপনি থ্রেডটি চালিয়ে যেতে চান এমন ক্ষেত্রে ডেমন হিসাবে থ্রেড সেট করা কি কিছু নয়?
মিশেল পিকোলিনি

আপনি স্যার, আমার দিনের নায়ক। ঠিক আমি কী খুঁজছিলাম এবং যুক্ত করার মতো কোনও হ্রাস নেই।
বরফ

42

অন্যরা যেমন উল্লেখ করেছে, আদর্শটি হল একটি স্টপ ফ্ল্যাগ সেট করা। হালকা কিছু জন্য (থ্রেডের কোনও সাবক্লাসিং নেই, বৈশ্বিক চলক নেই), ল্যাম্বডা কলব্যাক একটি বিকল্প। (এতে প্রথম বন্ধনীগুলি নোট করুন if stop()))

import threading
import time

def do_work(id, stop):
    print("I am thread", id)
    while True:
        print("I am thread {} doing something".format(id))
        if stop():
            print("  Exiting loop.")
            break
    print("Thread {}, signing off".format(id))


def main():
    stop_threads = False
    workers = []
    for id in range(0,3):
        tmp = threading.Thread(target=do_work, args=(id, lambda: stop_threads))
        workers.append(tmp)
        tmp.start()
    time.sleep(3)
    print('main: done sleeping; time to stop the threads.')
    stop_threads = True
    for worker in workers:
        worker.join()
    print('Finis.')

if __name__ == '__main__':
    main()

সর্বদা ফ্লাশ করে এমন print()একটি pr()ফাংশন প্রতিস্থাপন ( sys.stdout.flush()) শেল আউটপুটটির নির্ভুলতা উন্নত করতে পারে।

(শুধুমাত্র উইন্ডোজ / অ্যাক্লিপস / পাইথন 3.3 এ পরীক্ষিত)


1
লিনাক্স / পাইথন ২.7 এ যাচাইকৃত, কবজির মতো কাজ করে। এটি সরকারী উত্তর হওয়া উচিত, এটি অনেক সহজ।
পল কেনজোরা

1
লিনাক্স উবুন্টু সার্ভার 17.10 / পাইথন 3.6.3 এ যাচাই করা হয়েছে এবং এটি কাজ করে।
মার্কোস

1
2.7 তেও যাচাই করা হয়েছে। এমন সুন্দর উত্তর!
সিলগন

pr()ফাংশন কী ?
আল্পার

35

এটি থ্রেড 2 - কেলেবল থ্রেড (পাইথন রেসিপি) এর উপর ভিত্তি করে

আপনাকে পাইথ্রেডস্টেট_সেট্যাসিএনএক্সসি () কল করতে হবে, যা কেবল সিটাইপের মাধ্যমে উপলব্ধ।

এটি কেবল পাইথন ২.7.৩ এ পরীক্ষা করা হয়েছে, তবে এটি সাম্প্রতিক অন্যান্য ২.x রিলিজের সাথে কাজ করার সম্ভাবনা রয়েছে।

import ctypes

def terminate_thread(thread):
    """Terminates a python thread from another thread.

    :param thread: a threading.Thread instance
    """
    if not thread.isAlive():
        return

    exc = ctypes.py_object(SystemExit)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
        ctypes.c_long(thread.ident), exc)
    if res == 0:
        raise ValueError("nonexistent thread id")
    elif res > 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(thread.ident, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")

আমি আমার থ্রেডগুলিকে একটি উপহার দিতে এরকম কিছু ব্যবহার করছি KeyboardInterruptযাতে তারা পরিষ্কার করার সুযোগ পায়। যদি তারা এর পরেও ঝুলে থাকে তবে SystemExitউপযুক্ত, বা কেবলমাত্র টার্মিনাল থেকে প্রক্রিয়াটি মেরে ফেলুন।
ড্রিভিকো

থ্রেডটি বর্তমানে কার্যকর করা থাকলে এটি কাজ করে। থ্রেডটি সিস্টস্কলে থাকলে এটি কাজ করে না; ব্যতিক্রম চুপচাপ উপেক্ষা করা হবে।
ম্যাথিয়াস উরলিচস

@ ম্যাথিয়াস অরলিচ কোনও থ্রেড এক্সিকিউশন স্টেট কী তা সনাক্ত করতে, সতর্কতা মুদ্রণ করতে বা পুনরায় চেষ্টা করতে সক্ষম সে সম্পর্কে কী ধারণা দেয়?
জোহান ডাহলিন

1
@ জোহানডাহলিন আপনি কিছুটা অপেক্ষা করতে পারেন (যা আপনি যদি আবার চেষ্টা করতে চান তবে আপনাকে যা করতে হবে) এবং তারপরে আইসালাইভ () পরীক্ষা করুন। যাই হোক না কেন, এটি কাজ করার সময়, আমি গ্যারান্টিও দেব না যে এটি প্রায় ঝুঁকিপূর্ণ উল্লেখগুলি ছাড়বে না। যদিও সিপিথনে থ্রেড কিলিং নিরাপদ করা সম্ভব হয়েছে তবুও এর যথাযথ ব্যবহারের মাধ্যমে pthread_cleanup_push()/_pop()সঠিকভাবে বাস্তবায়নের জন্য এটি অনেক কাজ হবে এবং এটি দোভাষী হিসাবে ধীরগতির হয়ে যাবে।
ম্যাথিয়াস উরলিচস

32

কোনও থ্রেডকে সহযোগিতা না করে জোর করে কখনও হত্যা করা উচিত নয়।

থ্রেডকে হত্যা করা এমন কোনও গ্যারান্টি সরিয়ে দেয় যা চেষ্টা করে / অবশেষে ব্লক সেট আপ করে দেয় যাতে আপনি লকগুলি তালাবদ্ধ রাখতে পারেন, ফাইলগুলি খোলা থাকতে পারে ইত্যাদি remove

কেবলমাত্র যখন আপনি তর্ক করতে পারেন যে জোর করে থ্রেডগুলি হত্যা করা একটি ভাল ধারণাটি হ'ল একটি প্রোগ্রাম দ্রুত মারা যায়, তবে কখনও একক থ্রেড হয় না।


11
কেবল একটি থ্রেড বলা এত কঠিন কেন, আপনি আপনার বর্তমান লুপটি শেষ করার পরে নিজেকে হত্যা করুন ... আমি এটি পাই না।
মেহেদী

2
"লুপ" শনাক্ত করার জন্য সিপিইউতে এমন কোনও ব্যবস্থা তৈরি করা হয়নি, আপনি যে ধরনের প্রত্যাশা করতে পারেন তা হ'ল লুপের অভ্যন্তরে থাকা কোডটি একবার বের হয়ে গেলে এটি চেক করবে some থ্রেড সিঙ্ক্রোনাইজেশন হ্যান্ডেল করার সঠিক উপায়টি সমবায়িক উপায়গুলি দ্বারা, স্থগিতকরণ, পুনরায় শুরু করা এবং থ্রেডগুলি হত্যার কাজগুলি এমন ফাংশন যা ডিবাগার এবং অপারেটিং সিস্টেমের জন্য বোঝানো হয়, অ্যাপ্লিকেশন কোড নয়।
লাসে ভি। কার্লসেন

2
@ মেহেদী: আমি যদি (ব্যক্তিগতভাবে) থ্রেডে কোডটি লিখছি তবে হ্যাঁ, আমি আপনার সাথে একমত হই। তবে এমন কেস রয়েছে যেখানে আমি তৃতীয় পক্ষের লাইব্রেরিগুলি চালাচ্ছি এবং সেই কোডটির প্রয়োগকারী লুপটিতে আমার অ্যাক্সেস নেই। অনুরোধ করা বৈশিষ্ট্যের জন্য এটি একটি ব্যবহারের কেস।
ড্যান এইচ

@ ড্যানহ এটি তৃতীয় পক্ষের কোডের সাথে আরও খারাপ কারণ এটি কী ক্ষতি করতে পারে তা আপনার কোনও ধারণা নেই। যদি আপনার তৃতীয় পক্ষের লাইব্রেরিটি যথেষ্ট পরিমাণে শক্ত না হয় যে এটি হত্যা করা প্রয়োজন, তবে আপনার এইগুলির মধ্যে একটি করা উচিত: (1) লেখককে সমস্যাটি সমাধান করতে বলুন, (২) অন্য কিছু ব্যবহার করুন। যদি আপনার সত্যিই কোনও বিকল্প না থাকে, তবে সেই কোডটি একটি পৃথক প্রক্রিয়াতে রাখা নিরাপদ হওয়া উচিত কারণ কিছু সংস্থান কেবলমাত্র একক প্রক্রিয়ার মধ্যে ভাগ করা হয়।
ফিল 1970

25

পাইথনে, আপনি কেবল কোনও থ্রেড সরাসরি মারতে পারবেন না।

থ্রেডিং ব্যবহার না করে যদি আপনার সত্যিই কোনও থ্রেড (!) থাকা দরকার না হয় তবে আপনি কী করতে পারেন প্যাকেজটি হ'ল মাল্টিপ্রসেসিং প্যাকেজটি ব্যবহার করা । এখানে, একটি প্রক্রিয়া হত্যা করতে, আপনি কেবল পদ্ধতিটি কল করতে পারেন:

yourProcess.terminate()  # kill the process!

পাইথন আপনার প্রক্রিয়াটি মেরে ফেলবে ( TerminateProcess()কলটি দিয়ে উইন্ডোজ চলাকালীন সিগ্টারএম সিগন্যালের মাধ্যমে ইউনিক্সে )। একটি সারি বা পাইপ ব্যবহার করার সময় এটি ব্যবহার করার জন্য মনোযোগ দিন! (এটি কাতারে / পাইপে ডেটাটিকে দূষিত করতে পারে)

নোট করুন এবং যথাক্রমে একই পদ্ধতিতে multiprocessing.Eventএবং multiprocessing.Semaphoreকাজটি in আসলে, প্রথমগুলি হ'ল পরের ক্লোনগুলি।threading.Eventthreading.Semaphore

আপনার যদি সত্যিই একটি থ্রেড ব্যবহার করা দরকার হয়, সরাসরি এটি হত্যা করার কোনও উপায় নেই। আপনি যা করতে পারেন তা হ'ল একটি ব্যবহার করা "ডেমন থ্রেড" ব্যবহার করা । আসলে, পাইথনে, একটি থ্রেডকে ডেমন হিসাবে পতাকাঙ্কিত করা যেতে পারে :

yourThread.daemon = True  # set the Thread as a "daemon thread"

যখন কোনও জীবন্ত নন-ডেমন থ্রেড না রেখে মূল প্রোগ্রামটি প্রস্থান করবে। অন্য কথায়, যখন আপনার মূল থ্রেড (যা অবশ্যই একটি ডেমন থ্রেড) কাজ শেষ করবে, তখনও কিছু ডেমনের থ্রেড কাজ করে থাকলেও প্রোগ্রামটি প্রস্থান করবে।

নোট করুন যে এর daemonআগে যেমন একটি থ্রেড সেট করা প্রয়োজনstart() পদ্ধতিটি !

অবশ্যই আপনি ব্যবহার করতে পারেন, এবং করা উচিত daemon এমনকিmultiprocessing । এখানে, যখন প্রধান প্রক্রিয়াটি প্রস্থান করে, তখন এটির সমস্ত ডিমনিক শিশু প্রক্রিয়াগুলি বন্ধ করার চেষ্টা করে।

শেষ অবধি, দয়া করে নোট করুন sys.exit()এবং os.kill()পছন্দগুলি নয়।


14

আপনি থ্রেডে ট্রেস ইনস্টল করে একটি থ্রেডকে হত্যা করতে পারেন যা থ্রেড থেকে প্রস্থান করবে। একটি সম্ভাব্য বাস্তবায়নের জন্য সংযুক্ত লিঙ্কটি দেখুন।

পাইথনে একটি থ্রেড মেরে ফেলুন


আমি ইতিমধ্যে এটি দেখেছি। এই সমাধানটি স্ব-কিল্ড পতাকা চেকের উপর ভিত্তি করে
হঠাৎ করে Def

1
এখানে কয়েকটি উত্তরগুলির মধ্যে একটি যা আসলে কাজ করে
পঙ্কডুডল

5
এই সমাধানের সাথে দুটি সমস্যা: (ক) sys.settrace () দিয়ে ট্রেসার ইনস্টল করা আপনার থ্রেডটি ধীর করে দেবে। এটি গুনে সীমাবদ্ধ হলে 10 গুণ হিসাবে ধীর। (খ) কোনও সিস্টেম কলে থাকার সময় আপনার থ্রেডটিকে প্রভাবিত করবে না।
ম্যাথিয়াস উরলিচস

10

আপনি স্পষ্টভাবে আহ্বান করা হয় তাহলে time.sleep()আপনার থ্রেড (বলুন পোলিং কিছু বহিরাগত পরিষেবা) অংশ হিসেবে করেন ফিলিপ এর পদ্ধতি উপর একটি উন্নতি মধ্যে সময়সীমার ব্যবহার করা event'র wait()যেখানেই থাকুন না কেন পদ্ধতিsleep()

উদাহরণ স্বরূপ:

import threading

class KillableThread(threading.Thread):
    def __init__(self, sleep_interval=1):
        super().__init__()
        self._kill = threading.Event()
        self._interval = sleep_interval

    def run(self):
        while True:
            print("Do Something")

            # If no kill signal is set, sleep for the interval,
            # If kill signal comes in while sleeping, immediately
            #  wake up and handle
            is_killed = self._kill.wait(self._interval)
            if is_killed:
                break

        print("Killing Thread")

    def kill(self):
        self._kill.set()

তারপরে এটি চালানো

t = KillableThread(sleep_interval=5)
t.start()
# Every 5 seconds it prints:
#: Do Something
t.kill()
#: Killing Thread

আইং wait()পরিবর্তে ব্যবহার sleep()করার এবং ইভেন্টটি নিয়মিত পরীক্ষা করার সুবিধাটি হ'ল আপনি দীর্ঘ ঘুমের মধ্যে প্রোগ্রাম করতে পারেন, থ্রেডটি প্রায় সঙ্গে সঙ্গে বন্ধ হয়ে যায় (যখন আপনি অন্যথায় sleep()ইঙ্গিত করবেন) এবং আমার মতে প্রস্থানটি হ্যান্ডল করার কোডটি উল্লেখযোগ্যভাবে সহজ is ।


3
কেন এই পোস্টটি হ্রাস করা হয়েছিল? ডাব্লু / এই পোস্টে কি ভুল? আমার যা দরকার তা
হ'ল

9

আপনি যদি কোনও সুতো না মারেন তবে ভাল। থ্রেডের চক্রের মধ্যে "চেষ্টা" ব্লকটি প্রবর্তন করা এবং আপনি থ্রেডটি থামাতে চাইলে একটি ব্যতিক্রম ছুঁড়ে ফেলার উপায় হতে পারে (উদাহরণস্বরূপ বিরতি / রিটার্ন / ... যা আপনার / যখন / ... বন্ধ করে দেয়)। আমি এটি আমার অ্যাপ্লিকেশনটিতে ব্যবহার করেছি এবং এটি কাজ করে ...


8

Thread.stopনিম্নলিখিত উদাহরণ কোড হিসাবে প্রদর্শিত কোনও পদ্ধতি কার্যকরভাবে বাস্তবায়ন করা সম্ভব :

import sys
import threading
import time


class StopThread(StopIteration):
    pass

threading.SystemExit = SystemExit, StopThread


class Thread2(threading.Thread):

    def stop(self):
        self.__stop = True

    def _bootstrap(self):
        if threading._trace_hook is not None:
            raise ValueError('Cannot run thread with tracing!')
        self.__stop = False
        sys.settrace(self.__trace)
        super()._bootstrap()

    def __trace(self, frame, event, arg):
        if self.__stop:
            raise StopThread()
        return self.__trace


class Thread3(threading.Thread):

    def _bootstrap(self, stop_thread=False):
        def stop():
            nonlocal stop_thread
            stop_thread = True
        self.stop = stop

        def tracer(*_):
            if stop_thread:
                raise StopThread()
            return tracer
        sys.settrace(tracer)
        super()._bootstrap()

###############################################################################


def main():
    test1 = Thread2(target=printer)
    test1.start()
    time.sleep(1)
    test1.stop()
    test1.join()
    test2 = Thread2(target=speed_test)
    test2.start()
    time.sleep(1)
    test2.stop()
    test2.join()
    test3 = Thread3(target=speed_test)
    test3.start()
    time.sleep(1)
    test3.stop()
    test3.join()


def printer():
    while True:
        print(time.time() % 1)
        time.sleep(0.1)


def speed_test(count=0):
    try:
        while True:
            count += 1
    except StopThread:
        print('Count =', count)

if __name__ == '__main__':
    main()

Thread3বর্গ প্রায় 33% তুলনায় দ্রুততর কোড রান মনে হচ্ছে Thread2বর্গ।


3
self.__stopথ্রেডে সেট হয়ে যাওয়ার জন্য চেকগুলি ইনজেক্ট করার এটি একটি চতুর উপায় । মনে রাখবেন যে এখানে অন্যান্য সমাধানগুলির বেশিরভাগের মতো এটি আসলে একটি ব্লকিং কলকে বাধাগ্রস্ত করবে না, যেহেতু ট্রেস ফাংশনটি কেবল তখনই একটি নতুন স্থানীয় সুযোগ প্রবেশ করানো হয় called এছাড়াও লক্ষণীয় যে sys.settraceসত্যিকার অর্থে ডিবাগার, প্রোফাইল ইত্যাদি বাস্তবায়নের জন্য এবং এগুলি সিপিথনের একটি বাস্তবায়ন বিশদ হিসাবে বিবেচিত হয় এবং এটি পাইথনের অন্যান্য বাস্তবায়নেও নিশ্চয়তা দেয় না।
ড্যানো

3
@ স্পেনো: Thread2ক্লাসে সবচেয়ে বড় সমস্যা হ'ল এটি কোডটি প্রায় দশগুণ কম চালায়। কিছু লোক এখনও এটি গ্রহণযোগ্য বলে মনে করতে পারে।
নোকটিস স্কাইটিওয়ার

এটির উপর +1 কোড প্রয়োগ কার্যকরভাবে ধীর করে দেয় .. আমি পরামর্শ দেব যে এই সমাধানটির লেখক উত্তরে এই তথ্য অন্তর্ভুক্ত করুন।
বিশাল

6
from ctypes import *
pthread = cdll.LoadLibrary("libpthread-2.15.so")
pthread.pthread_cancel(c_ulong(t.ident))

টি আপনারThread অবজেক্ট।

পাইথন উত্সটি পড়ুন ( Modules/threadmodule.cএবং Python/thread_pthread.h) আপনি দেখতে পাচ্ছেন যে Thread.identএটি একটি pthread_tপ্রকার, তাই pthreadঅজগর ব্যবহারে আপনি যে কোনও কাজ করতে পারেন libpthread


এবং আপনি কীভাবে উইন্ডোজ এ করবেন?
আইচুকস

12
আপনি না; উইন্ডোজেও নয় লিনাক্সেও নয়। কারণ: আপনি যখন এটি করছেন তখন প্রশ্নযুক্ত থ্রেডটি জিআইএলকে ধরে রাখতে পারে (আপনি সিটিতে ডাকলে পাইথন জিলকে প্রকাশ করে)। যদি এটি হয় তবে আপনার প্রোগ্রামটি তাত্ক্ষণিকভাবে অচল করে দেবে। তা না হলেও, শেষ পর্যন্ত: ব্লকগুলি কার্যকর করা হবে না ইত্যাদি ইত্যাদি, সুতরাং এটি একটি খুব অনিরাপদ ধারণা।
ম্যাথিয়াস উরলিচস

6

একটি থ্রেড মেরে নীচের কাজের জন্য ব্যবহার করা যেতে পারে:

kill_threads = False

def doSomething():
    global kill_threads
    while True:
        if kill_threads:
            thread.exit()
        ......
        ......

thread.start_new_thread(doSomething, ())

এটি মূল থ্রেড থেকে, যার কোডটি অন্য মডিউলে রচিত, থ্রেডেমেটিকের সমাপ্তির জন্যও ব্যবহার করা যেতে পারে। আমরা সেই মডিউলে একটি গ্লোবাল ভেরিয়েবল ঘোষণা করতে পারি এবং এটি মডিউলটিতে থাকা থ্রেড / গুলি সমাপ্ত করতে ব্যবহার করতে পারি।

আমি সাধারণত প্রোগ্রামটি প্রস্থান করার সময় সমস্ত থ্রেড শেষ করতে এটি ব্যবহার করি। এটি থ্রেড / গুলি সমাপ্ত করার উপযুক্ত উপায় নাও হতে পারে তবে সহায়তা করতে পারে।


থাম্বস আপ। বুঝতে সহজ।
alyssaeliyah

6

আমি এই খেলায় দেরি করে চলেছি, তবে আমি একই ধরণের প্রশ্ন নিয়ে কুস্তি করছি এবং নিম্নলিখিতটি উভয়ই আমার পক্ষে পুরোপুরি সমস্যার সমাধান করতে উপস্থিত হয়েছে এবং ডেমোনাইজড সাব-থ্রেডটি প্রস্থান করার সময় আমাকে কিছু বেসিক থ্রেড স্টেট চেকিং এবং ক্লিনআপ করতে দেয়:

import threading
import time
import atexit

def do_work():

  i = 0
  @atexit.register
  def goodbye():
    print ("'CLEANLY' kill sub-thread with value: %s [THREAD: %s]" %
           (i, threading.currentThread().ident))

  while True:
    print i
    i += 1
    time.sleep(1)

t = threading.Thread(target=do_work)
t.daemon = True
t.start()

def after_timeout():
  print "KILL MAIN THREAD: %s" % threading.currentThread().ident
  raise SystemExit

threading.Timer(2, after_timeout).start()

উৎপাদনের:

0
1
KILL MAIN THREAD: 140013208254208
'CLEANLY' kill sub-thread with value: 2 [THREAD: 140013674317568]

এই একটি উত্তরের উত্তর যা তালিকায় আরও বেশি হওয়া উচিত
২ro

কেন উত্থাপন করবে SystemExitউপর after_timeoutথ্রেড মূল থ্রেড (যা কেবল এই উদাহরণে প্রস্থান সাবেক অপেক্ষায় হয়) কিছু না?
ডেভিস হেরিং 17

@ ডেভিস হেরিং আমি নিশ্চিত না আপনি কী পাচ্ছেন। সিস্টেমএক্সিট মূল থ্রেডটিকে হত্যা করে, আপনি কেন মনে করেন যে এটি মূল থ্রেটে কিছু করবে? এই কলটি ছাড়াই, প্রোগ্রামটি কেবলমাত্র শিশু থ্রেডের জন্য অপেক্ষা করতে থাকবে। আপনি মূল থ্রেডটি মারতে ctrl + c বা অন্য কোনও উপায় ব্যবহার করতে পারেন তবে এটি একটি উদাহরণ।
slumtrimpet

@ স্লাম্ট্রিম্পেট: SystemExitকেবল দুটি বিশেষ বৈশিষ্ট্য রয়েছে: এটি কোনও ট্রেসব্যাক তৈরি করে না (যখন কোনও থ্রেড একটি নিক্ষেপ করে বেরিয়ে আসে), এবং যদি মূল থ্রেড একটি নিক্ষেপ করে প্রস্থান করে তবে এটি প্রস্থান স্থিতি নির্ধারণ করে (অন্যদিকে অন্য ডিমন-থ্রেডের অপেক্ষার জন্য অপেক্ষা করে প্রস্থান করা).
ডেভিস হেরিং

@ ডেভিস হেরিং ওহ, আমি পেয়েছি। পুরোপুরি ভাবে তোমার সাথে একমত. আমরা এখানে যা করেছি তা ভুল করেছিলাম এবং আপনার মন্তব্যকে ভুল বুঝছিলাম।
slumtrimpet

4

আমি একটি জিনিস যোগ করতে চাই যে আপনি যদি পাইথন লাইব থ্রেডিংয়ে অফিসিয়াল ডকুমেন্টেশন পড়ে থাকেন তবে "দানবিক" থ্রেডের ব্যবহার এড়ানো বাঞ্ছনীয়, যখন আপনি থ্রেড হঠাৎ শেষ করতে চান না, পাওলো রোভেলি উল্লিখিত পতাকাটি সহ ।

অফিসিয়াল ডকুমেন্টেশন থেকে:

ডেমনের থ্রেডগুলি হঠাৎ বন্ধ হয়ে যায়। তাদের সংস্থানগুলি (যেমন ওপেন ফাইল, ডাটাবেস লেনদেন ইত্যাদি) সঠিকভাবে প্রকাশিত হতে পারে না। আপনি যদি চান যে আপনার থ্রেডগুলি কৃপণভাবে থামতে পারে তবে এগুলি ডি-ডেমোনিক করুন এবং কোনও ইভেন্টের মতো উপযুক্ত সিগন্যালিং ব্যবস্থা ব্যবহার করুন।

আমি মনে করি যে ডেমোনিক থ্রেডগুলি তৈরি করা আপনার প্রয়োগের উপর নির্ভর করে তবে সাধারণভাবে (এবং আমার মতে) তাদের হত্যা করা বা ডিমনিক না করা ভাল। মাল্টিপ্রসেসিংয়ে আপনি is_alive()প্রক্রিয়া স্থিতি পরীক্ষা করতে এবং সেগুলি শেষ করার জন্য "সমাপ্ত" ব্যবহার করতে পারেন (এছাড়াও আপনি জিআইএল সমস্যাগুলি এড়াতে পারেন)। আপনি উইন্ডোতে আপনার কোডটি কার্যকর করার সময় আপনি কখনও কখনও আরও সমস্যার সন্ধান করতে পারেন।

এবং সর্বদা মনে রাখবেন যে আপনার যদি "লাইভ থ্রেড" থাকে তবে পাইথন ইন্টারপ্রেটার তাদের জন্য অপেক্ষা করবে। (হঠাৎ করে যদি বিষয়টি শেষ না হয় তবে এই ডেমোনিক আপনাকে সাহায্য করতে পারে)।


4
আমি শেষ অনুচ্ছেদ বুঝতে পারি না।
tshpang

@Tshepang মানে যদি আপনার অ্যাপ্লিকেশনের মধ্যে কোন চলমান অ দৈত্যাদিসংক্রান্ত থ্রেড আছে, পাইথন ইন্টারপ্রেটার পর্যন্ত চলমান অব্যাহত থাকবে সব অ ডেমন থ্রেড আছে কাজ । প্রোগ্রামটি শেষ হয়ে গেলে থ্রেড (গুলি) শেষ হয় কিনা সেদিকে খেয়াল না রাখলে তাদের ডেমন তৈরি করা কার্যকর হতে পারে।
টম মাইলডেল্টেন

3

স্টপিট এই উদ্দেশ্যে একটি গ্রন্থাগার নির্মিত হয়েছে । যদিও এখানে তালিকাভুক্ত একই সতর্কতাগুলির কিছু এখনও প্রয়োগ রয়েছে, কমপক্ষে এই গ্রন্থাগারটি বর্ণিত লক্ষ্য অর্জনের জন্য একটি নিয়মিত, পুনরাবৃত্তিযোগ্য কৌশল উপস্থাপন করে।


1

যদিও এটা বরং পুরানো এর এই কিছু জন্য একটি সহজ সমাধান হতে পারে:

একটি সামান্য মডিউল যা থ্রেডিংয়ের মডিউল কার্যকারিতা প্রসারিত করে - একটি থ্রেডকে অন্য থ্রেডের প্রসঙ্গে ব্যতিক্রম বাড়াতে অনুমতি দেয়। উত্থাপন দ্বারা SystemExit, আপনি শেষ পর্যন্ত পাইথন থ্রেডগুলি হত্যা করতে পারেন।

import threading
import ctypes     

def _async_raise(tid, excobj):
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(excobj))
    if res == 0:
        raise ValueError("nonexistent thread id")
    elif res > 1:
        # """if it returns a number greater than one, you're in trouble, 
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
        raise SystemError("PyThreadState_SetAsyncExc failed")

class Thread(threading.Thread):
    def raise_exc(self, excobj):
        assert self.isAlive(), "thread must be started"
        for tid, tobj in threading._active.items():
            if tobj is self:
                _async_raise(tid, excobj)
                return

        # the thread was alive when we entered the loop, but was not found 
        # in the dict, hence it must have been already terminated. should we raise
        # an exception here? silently ignore?

    def terminate(self):
        # must raise the SystemExit type, instead of a SystemExit() instance
        # due to a bug in PyThreadState_SetAsyncExc
        self.raise_exc(SystemExit)

সুতরাং, এটি "থ্রেডটিকে অন্য থ্রেডের প্রসঙ্গে ব্যতিক্রম বাড়াতে" অনুমতি দেয় এবং এইভাবে, সমাপ্ত থ্রেড নিয়মিত কোনও বিসর্জনিত পতাকাটি পরীক্ষা না করেই সমাপ্তি পরিচালনা করতে পারে।

তবে এর আসল উত্স অনুসারে এই কোডটি নিয়ে কিছু সমস্যা রয়েছে।

  • পাইথন বাইটকোড কার্যকর করার সময় ব্যতিক্রমগুলি উত্থাপিত হবে। যদি আপনার থ্রেডটি কোনও দেশীয় / অন্তর্নির্মিত ব্লকিং ফাংশনটিকে কল করে, কেবলমাত্র অজগর কোডটিতে মৃত্যুদন্ড কার্যকর হলেই ব্যতিক্রম উত্থাপিত হবে।
    • অন্তর্নির্মিত ফাংশনটি অভ্যন্তরীণভাবে পাইআর_ক্র্লেয়ার () কল করে যদি একটি সমস্যা রয়েছে, যা কার্যকরভাবে আপনার মুলতুবি ব্যতিক্রম বাতিল করে দেবে। আপনি এটি আবার বাড়াতে চেষ্টা করতে পারেন।
  • কেবল ব্যতিক্রম প্রকারগুলি নিরাপদে উত্থাপিত হতে পারে। ব্যতিক্রম উদাহরণগুলি অপ্রত্যাশিত আচরণের কারণ হতে পারে এবং এইভাবে সীমাবদ্ধ।
    • উদাহরণস্বরূপ: t1.raise_exc (TypeError) এবং t1.raise_exc (TypeError ("blah")) নয়।
    • আইএমএইচও এটি একটি বাগ, এবং আমি এটি হিসাবে রিপোর্ট করেছি। আরও তথ্যের জন্য, http://mail.python.org/pipermail/python-dev/2006- অগাস্ট / 068158.html
  • আমি বিল্ট-ইন থ্রেড মডিউলটিতে এই ফাংশনটি প্রকাশ করতে বলেছিলাম, তবে যেহেতু সিটিপস একটি স্ট্যান্ডার্ড লাইব্রেরি হয়েছে (২.৩ হিসাবে), এবং এই
    বৈশিষ্ট্যটি বাস্তবায়ন- অজানস্টিক হওয়ার সম্ভাবনা নেই, তাই এটি অনস্পষ্ট অবস্থায় রাখতে পারে

0

এটি উইন্ডোজ 7-এ পাইউইন 32 এর সাথে কাজ করছে বলে মনে হচ্ছে

my_thread = threading.Thread()
my_thread.start()
my_thread._Thread__stop()

0

পিএমর হিন্টজেন্সস - এমকিউ- প্রকল্পের অন্যতম প্রতিষ্ঠাতা - বলেছেন, Ø এমকিউ ব্যবহার করা এবং লক, মিউটেক্স, ইভেন্ট ইত্যাদির মতো সিঙ্ক্রোনাইজেশন আদিমতা এড়ানো, একাধিক থ্রেডযুক্ত প্রোগ্রাম লেখার সানেষ্ট এবং সুরক্ষিত উপায়:

http://zguide.zeromq.org/py:all#Multithreading-with-ZeroMQ

এর মধ্যে একটি শিশু থ্রেড বলাও উচিত, এটির কাজটি বাতিল করা উচিত। এটি থ্রেডটি এমকিউ-সকেটের সাথে সজ্জিত করে এবং সেই সকেটে এই বার্তাটি বাতিল করার কথা বলে ভোট দেওয়ার মাধ্যমে পোলিং করা হবে।

লিঙ্কটি এমকিউ সহ মাল্টি-থ্রেডেড পাইথন কোডের একটি উদাহরণও সরবরাহ করে।


0

মনে করে, আপনি একই ফাংশনের একাধিক থ্রেড রাখতে চান, এটি আইডিতে একটিকে থামানো সবচেয়ে সহজ বাস্তবায়ন IMHO:

import time
from threading import Thread

def doit(id=0):
    doit.stop=0
    print("start id:%d"%id)
    while 1:
        time.sleep(1)
        print(".")
        if doit.stop==id:
            doit.stop=0
            break
    print("end thread %d"%id)

t5=Thread(target=doit, args=(5,))
t6=Thread(target=doit, args=(6,))

t5.start() ; t6.start()
time.sleep(2)
doit.stop =5  #kill t5
time.sleep(2)
doit.stop =6  #kill t6

সুন্দর জিনিসটি এখানে, আপনার একাধিক একই এবং বিভিন্ন ফাংশন থাকতে পারে এবং সেগুলি বন্ধ করে দিতে পারেন functionname.stop

আপনি যদি ফাংশনটির কেবল একটি থ্রেড রাখতে চান তবে আপনাকে আইডি মনে রাখার দরকার নেই। বন্ধ করুন, যদি doit.stop> 0।


0

কাস্টমাইজড ফাংশন সহ কিলাবলথ্রেড সাবক্লাস তৈরি করতে কেবল @ এসসিবির ধারণাটি (যা আমার যা প্রয়োজন ঠিক তেমনটিই তৈরি করা):

from threading import Thread, Event

class KillableThread(Thread):
    def __init__(self, sleep_interval=1, target=None, name=None, args=(), kwargs={}):
        super().__init__(None, target, name, args, kwargs)
        self._kill = Event()
        self._interval = sleep_interval
        print(self._target)

    def run(self):
        while True:
            # Call custom function with arguments
            self._target(*self._args)

        # If no kill signal is set, sleep for the interval,
        # If kill signal comes in while sleeping, immediately
        #  wake up and handle
        is_killed = self._kill.wait(self._interval)
        if is_killed:
            break

    print("Killing Thread")

def kill(self):
    self._kill.set()

if __name__ == '__main__':

    def print_msg(msg):
        print(msg)

    t = KillableThread(10, print_msg, args=("hello world"))
    t.start()
    time.sleep(6)
    print("About to kill thread")
    t.kill()

স্বাভাবিকভাবেই, @ এসবিসি-র মতো, থ্রেডটি থামাতে নতুন লুপটি চালানোর জন্য অপেক্ষা করে না। এই উদাহরণে, আপনি থ্রেডটি সম্পূর্ণ হওয়ার জন্য আরও 4 সেকেন্ড অপেক্ষা না করে "থ্রেড মারতে চলেছেন" এর পরে ঠিক "কিলিং থ্রেড" বার্তাটি মুদ্রিত দেখতে পাবেন (যেহেতু আমরা ইতিমধ্যে 6 সেকেন্ডের জন্য ঘুমিয়েছি)।

কিল্যাবলথ্রেড কনস্ট্রাক্টরের দ্বিতীয় যুক্তি হ'ল আপনার কাস্টম ফাংশন (এখানে print_msg)। আরগস আর্গুমেন্টটি সেই যুক্তি যা এখানে ফাংশন (("হ্যালো ওয়ার্ল্ড")) ​​কল করার সময় ব্যবহৃত হবে।


0

@ কোজিরুকুকের উত্তরে যেমন উল্লেখ করা হয়েছে , ট্রেস ইনস্টল করার কাজ রয়েছে। যেহেতু এই উত্তরে কোনও কোড নেই, তাই এখানে ব্যবহারের জন্য প্রস্তুত উদাহরণ রয়েছে:

import sys, threading, time 

class TraceThread(threading.Thread): 
    def __init__(self, *args, **keywords): 
        threading.Thread.__init__(self, *args, **keywords) 
        self.killed = False
    def start(self): 
        self._run = self.run 
        self.run = self.settrace_and_run
        threading.Thread.start(self) 
    def settrace_and_run(self): 
        sys.settrace(self.globaltrace) 
        self._run()
    def globaltrace(self, frame, event, arg): 
        return self.localtrace if event == 'call' else None
    def localtrace(self, frame, event, arg): 
        if self.killed and event == 'line': 
            raise SystemExit() 
        return self.localtrace 

def f(): 
    while True: 
        print('1') 
        time.sleep(2)
        print('2') 
        time.sleep(2)
        print('3') 
        time.sleep(2)

t = TraceThread(target=f) 
t.start() 
time.sleep(2.5) 
t.killed = True

এটা তোলে মুদ্রিত পর স্টপ 1এবং 23মুদ্রিত হয় না।


-1

আপনি কোনও প্রক্রিয়াতে আপনার আদেশটি কার্যকর করতে পারেন এবং তারপরে প্রক্রিয়া আইডি ব্যবহার করে এটি হত্যা করতে পারেন। আমার দুটি থ্রেডের মধ্যে সিঙ্ক করা দরকার যার একটি নিজে থেকে ফিরে আসে না।

processIds = []

def executeRecord(command):
    print(command)

    process = subprocess.Popen(command, stdout=subprocess.PIPE)
    processIds.append(process.pid)
    print(processIds[0])

    #Command that doesn't return by itself
    process.stdout.read().decode("utf-8")
    return;


def recordThread(command, timeOut):

    thread = Thread(target=executeRecord, args=(command,))
    thread.start()
    thread.join(timeOut)

    os.kill(processIds.pop(), signal.SIGINT)

    return;

-1

সেটডেমোন (সত্য) দিয়ে সাব থ্রেডটি শুরু করুন।

def bootstrap(_filename):
    mb = ModelBootstrap(filename=_filename) # Has many Daemon threads. All get stopped automatically when main thread is stopped.

t = threading.Thread(target=bootstrap,args=('models.conf',))
t.setDaemon(False)

while True:
    t.start()
    time.sleep(10) # I am just allowing the sub-thread to run for 10 sec. You can listen on an event to stop execution.
    print('Thread stopped')
    break

-2

এটি একটি খারাপ উত্তর, মন্তব্য দেখুন

এটি কীভাবে করবেন তা এখানে:

from threading import *

...

for thread in enumerate():
    if thread.isAlive():
        try:
            thread._Thread__stop()
        except:
            print(str(thread.getName()) + ' could not be terminated'))

এটি কয়েক সেকেন্ড দিন তারপরে আপনার থ্রেডটি বন্ধ করা উচিত। এছাড়াও পরীক্ষা করুনthread._Thread__delete()পদ্ধতিটিও ।

আমি thread.quit()সুবিধার জন্য একটি পদ্ধতি সুপারিশ করব । উদাহরণস্বরূপ, যদি আপনার থ্রেডে সকেট থাকে, আমি quit()আপনার সকেট-হ্যান্ডেল শ্রেণিতে একটি পদ্ধতি তৈরি করার, সকেটটি সমাপ্ত করার, এবং তারপরে একটি thread._Thread__stop()অভ্যন্তর চালানোর পরামর্শ দেব quit()


আমাকে আমার থ্রেডিংয়ের অভ্যন্তরে স্ব ._ড্রেড_স্টপ () ব্যবহার করতে হয়েছিল it থ্রেড অবজেক্ট এটিকে থামানোর জন্য। আমি বুঝতে পারি না কেন একটি সাধারণ সেলফ জোইন () উদাহরণ (কোড. activestate.com/recines/65448-thread-control-idiom ) এর মতো কাজ করে না।
হরিজয়

12
"এটি আসলে কোনও থ্রেড থামায় না" সম্পর্কিত আরও বিবরণ সহায়ক হবে।
2371

19
মূলত, পাইথনকে থ্রেডটি বন্ধ হয়ে গেছে তা বলা ছাড়া _Thread__stop পদ্ধতিতে কল করার কোনও প্রভাব নেই। এটি আসলে চালিয়ে যেতে পারে। উদাহরণস্বরূপ gist.github.com/2787191 দেখুন ।
ব্লুহর্ন

35
এটি সাধারণ ভুল। থ্রেড হিসাবে_Thread__stop() নিছক চিহ্নিত করে, এটি আসলে থ্রেডটি থামায় না! এটি কখনও করবেন না। একটি পড়া আছে
dotancohen

-2

আপনার যদি সত্যিই উপ-টাস্কটি মেরে ফেলার দক্ষতার প্রয়োজন হয় তবে বিকল্প বাস্তবায়ন ব্যবহার করুন। multiprocessingএবং geventউভয়ই নির্বিচারে একটি "থ্রেড" হত্যার পক্ষে সমর্থন করে।

পাইথনের থ্রেডিং বাতিলকরণ সমর্থন করে না। এমনকি চেষ্টা করবেন না. আপনার কোডটি অচলাবস্থা, দুর্নীতিগ্রস্থ বা মেমরি ফাঁস হওয়ার সম্ভাবনা রয়েছে বা অন্যান্য অপ্রত্যাশিত "আকর্ষণীয়" হার্ড-টু-ডিবাগ প্রভাব রয়েছে যা বিরল এবং অ-সংজ্ঞায়িতভাবে ঘটে।


2
... এবং হ্যাঁ, আমি জানি যে উভয়ই কঠোরভাবে "থ্রেডিং" নয়, তবে আপনার কোডটি তাদের মডেলের সাথে ফিট করে (বা ফিট করার জন্য তৈরি করা যেতে পারে) তবে তারা উভয়ই কাজ করে।
ম্যাথিয়াস উরলিচস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.