logo

Python | Olika sätt att döda en tråd

I allmänhet anses att döda trådar abrupt som en dålig programmeringspraxis. Att döda en tråd plötsligt kan lämna en kritisk resurs som måste stängas ordentligt öppen. Men du kanske vill döda en tråd när en viss tidsperiod har passerat eller ett avbrott har genererats. Det finns olika metoder för att döda en tråd i python.

  • Tar upp undantag i en pytontråd
  • Ställ in/återställ stoppflagga
  • Använder spår för att döda trådar
  • Använder multiprocessormodulen för att döda trådar
  • Döda Python-tråden genom att ställa in den som demon
  • Använda en dold funktion _stop()

Tar upp undantag i en python-tråd:
Denna metod använder funktionen PyThreadState_SetAsyncExc() att ta upp ett undantag i en tråd. Till exempel,



Python3








# Python program raising> # exceptions in a python> # thread> import> threading> import> ctypes> import> time> > class> thread_with_exception(threading.Thread):> >def> __init__(>self>, name):> >threading.Thread.__init__(>self>)> >self>.name>=> name> > >def> run(>self>):> ># target function of the thread class> >try>:> >while> True>:> >print>(>'running '> +> self>.name)> >finally>:> >print>(>'ended'>)> > >def> get_id(>self>):> ># returns id of the respective thread> >if> hasattr>(>self>,>'_thread_id'>):> >return> self>._thread_id> >for> id>, thread>in> threading._active.items():> >if> thread>is> self>:> >return> id> > >def> raise_exception(>self>):> >thread_id>=> self>.get_id()> >res>=> ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,> >ctypes.py_object(SystemExit))> >if> res>>1>:> >ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,>0>)> >print>(>'Exception raise failure'>)> > t1>=> thread_with_exception(>'Thread 1'>)> t1.start()> time.sleep(>2>)> t1.raise_exception()> t1.join()>

>

>

När vi kör koden ovan i en maskin och du kommer att märka, så fort funktionen raise_exception() anropas, avslutas målfunktionen run(). Detta beror på att så snart ett undantag görs, hoppar programkontrollen ut från try-blocket och run()-funktionen avslutas. Efter det kan join()-funktionen anropas för att döda tråden. I avsaknad av funktionen run_exception(), fortsätter målfunktionen run() att köras för alltid och join()-funktionen anropas aldrig för att döda tråden.

Ställ in/återställ stoppflagga:
För att döda en tråd kan vi deklarera en stoppflagga och denna flagga kommer att kontrolleras ibland av tråden. Till exempel

Python3


Linux gratis ipconfig



# Python program showing> # how to kill threads> # using set/reset stop> # flag> import> threading> import> time> def> run():> >while> True>:> >print>(>'thread running'>)> >global> stop_threads> >if> stop_threads:> >break> stop_threads>=> False> t1>=> threading.Thread(target>=> run)> t1.start()> time.sleep(>1>)> stop_threads>=> True> t1.join()> print>(>'thread killed'>)>

>

>

I koden ovan, så snart den globala variabeln stop_threads har ställts in, slutar målfunktionen run() och tråden t1 kan dödas genom att använda t1.join(). Men man kan avstå från att använda global variabel på grund av vissa skäl. För dessa situationer kan funktionsobjekt skickas för att tillhandahålla en liknande funktionalitet som visas nedan.

Python3




# Python program killing> # threads using stop> # flag> import> threading> import> time> def> run(stop):> >while> True>:> >print>(>'thread running'>)> >if> stop():> >break> > def> main():> >stop_threads>=> False> >t1>=> threading.Thread(target>=> run, args>=>(>lambda> : stop_threads, ))> >t1.start()> >time.sleep(>1>)> >stop_threads>=> True> >t1.join()> >print>(>'thread killed'>)> main()>

>

>

Funktionsobjektet som skickas i ovanstående kod returnerar alltid värdet för den lokala variabeln stop_threads. Detta värde kontrolleras i funktionen run(), och så snart stop_threads återställs avslutas run()-funktionen och tråden kan dödas.

Använda spår för att döda trådar:
Denna metod fungerar genom att installera spår i varje tråd. Varje spår avslutas av sig själv vid detektering av någon stimulans eller flagga, vilket omedelbart dödar den associerade tråden. Till exempel

Python3




# Python program using> # traces to kill threads> import> sys> import> trace> import> threading> import> time> class> thread_with_trace(threading.Thread):> >def> __init__(>self>,>*>args,>*>*>keywords):> >threading.Thread.__init__(>self>,>*>args,>*>*>keywords)> >self>.killed>=> False> >def> start(>self>):> >self>.__run_backup>=> self>.run> >self>.run>=> self>.__run> >threading.Thread.start(>self>)> >def> __run(>self>):> >sys.settrace(>self>.globaltrace)> >self>.__run_backup()> >self>.run>=> self>.__run_backup> >def> globaltrace(>self>, frame, event, arg):> >if> event>=>=> 'call'>:> >return> self>.localtrace> >else>:> >return> None> >def> localtrace(>self>, frame, event, arg):> >if> self>.killed:> >if> event>=>=> 'line'>:> >raise> SystemExit()> >return> self>.localtrace> >def> kill(>self>):> >self>.killed>=> True> def> func():> >while> True>:> >print>(>'thread running'>)> t1>=> thread_with_trace(target>=> func)> t1.start()> time.sleep(>2>)> t1.kill()> t1.join()> if> not> t1.isAlive():> >print>(>'thread killed'>)>

>

>

I den här koden är start() något modifierad för att ställa in systemspårningsfunktionen med settrace() . Den lokala spårningsfunktionen definieras så att, närhelst kill-flaggan (dödad) för respektive tråd sätts, uppstår ett SystemExit-undantag vid exekvering av nästa rad kod, vilket avslutar exekveringen av målfunktionen func. Nu kan tråden dödas med join().

Använda multiprocessormodulen för att döda trådar:
Multiprocessing-modulen i Python låter dig skapa processer på samma sätt som du skapar trådar med hjälp av trådningsmodulen. Gränssnittet för flertrådsmodulen liknar det för gängningsmodulen. Till exempel, i en given kod skapade vi tre trådar(processer) som räknas från 1 till 9.

Python3

osi referensmodell i nätverk




# Python program creating> # three threads> import> threading> import> time> # counts from 1 to 9> def> func(number):> >for> i>in> range>(>1>,>10>):> >time.sleep(>0.01>)> >print>(>'Thread '> +> str>(number)>+> ': prints '> +> str>(number>*>i))> # creates 3 threads> for> i>in> range>(>0>,>3>):> >thread>=> threading.Thread(target>=>func, args>=>(i,))> >thread.start()>

>

>

Funktionaliteten hos ovanstående kod kan också implementeras genom att använda multiprocessormodulen på ett liknande sätt, med mycket få ändringar. Se koden nedan.

Python3




# Python program creating> # thread using multiprocessing> # module> import> multiprocessing> import> time> def> func(number):> >for> i>in> range>(>1>,>10>):> >time.sleep(>0.01>)> >print>(>'Processing '> +> str>(number)>+> ': prints '> +> str>(number>*>i))> for> i>in> range>(>0>,>3>):> >process>=> multiprocessing.Process(target>=>func, args>=>(i,))> >process.start()>

>

>

Även om gränssnittet för de två modulerna är liknande, har de två modulerna väldigt olika implementeringar. Alla trådar delar globala variabler, medan processer är helt separata från varandra. Därför är avlivningsprocesser mycket säkrare jämfört med att döda trådar. Processklassen tillhandahålls en metod, avsluta() , för att döda en process. Nu, tillbaka till det ursprungliga problemet. Anta att vi i ovanstående kod vill döda alla processer efter att 0.03s har passerat. Denna funktionalitet uppnås med hjälp av multiprocessormodulen i följande kod.

Python3




# Python program killing> # a thread using multiprocessing> # module> import> multiprocessing> import> time> def> func(number):> >for> i>in> range>(>1>,>10>):> >time.sleep(>0.01>)> >print>(>'Processing '> +> str>(number)>+> ': prints '> +> str>(number>*>i))> # list of all processes, so that they can be killed afterwards> all_processes>=> []> for> i>in> range>(>0>,>3>):> >process>=> multiprocessing.Process(target>=>func, args>=>(i,))> >process.start()> >all_processes.append(process)> # kill all processes after 0.03s> time.sleep(>0.03>)> for> process>in> all_processes:> >process.terminate()>

>

>

Även om de två modulerna har olika implementeringar. Denna funktionalitet som tillhandahålls av multiprocessormodulen i ovanstående kod liknar att döda trådar. Därför kan multibearbetningsmodulen användas som en enkel alternativ närhelst vi måste implementera dödandet av trådar i Python.

Döda Python-tråden genom att ställa in den som demon:
Demonstrådar är de trådar som dödas när huvudprogrammet avslutas. Till exempel

Python3




import> threading> import> time> import> sys> def> func():> >while> True>:> >time.sleep(>0.5>)> >print>(>'Thread alive, and it won't die on program termination'>)> t1>=> threading.Thread(target>=>func)> t1.start()> time.sleep(>2>)> sys.exit()>

>

>

Lägg märke till att tråden t1 förblir vid liv och förhindrar att huvudprogrammet avslutas via sys.exit(). I Python blockerar alla levande icke-demonstrådar att huvudprogrammet avslutas. Medan själva demontrådarna dödas så snart huvudprogrammet avslutas. Med andra ord, så snart huvudprogrammet avslutas, dödas alla demontrådar. För att deklarera en tråd som demon, ställer vi in ​​nyckelordsargumentet, demon som True. Till exempel i den givna koden demonstrerar den egenskapen hos demontrådar.

Python3




# Python program killing> # thread using daemon> import> threading> import> time> import> sys> def> func():> >while> True>:> >time.sleep(>0.5>)> >print>(>'Thread alive, but it will die on program termination'>)> t1>=> threading.Thread(target>=>func)> t1.daemon>=> True> t1.start()> time.sleep(>2>)> sys.exit()>

>

>

Lägg märke till att tråden t1 dödas så snart huvudprogrammet avslutas. Denna metod visar sig vara extremt användbar i fall där programavslutning kan användas för att utlösa dödandet av trådar. Observera att i Python avslutas huvudprogrammet så snart alla icke-demon-trådar är döda, oavsett antalet demontrådar som är levande. Därför kan det hända att resurserna som innehas av dessa demontrådar, såsom öppna filer, databastransaktioner, etc. inte släpps korrekt. Den initiala kontrolltråden i ett pythonprogram är inte en demontråd. Att döda en tråd med våld rekommenderas inte om det inte är säkert känt att det inte kommer att orsaka några läckor eller dödläge.
Använda en dold funktion _stop():
För att döda en tråd använder vi den dolda funktionen _stop() denna funktion är inte dokumenterad men kan försvinna i nästa version av python.

Python3




# Python program killing> # a thread using ._stop()> # function> import> time> import> threading> class> MyThread(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>(MyThread,>self>).__init__(>*>args,>*>*>kwargs)> >self>._stop>=> threading.Event()> ># function using _stop function> >def> stop(>self>):> >self>._stop.>set>()> >def> stopped(>self>):> >return> self>._stop.isSet()> >def> run(>self>):> >while> True>:> >if> self>.stopped():> >return> >print>(>'Hello, world!'>)> >time.sleep(>1>)> t1>=> MyThread()> t1.start()> time.sleep(>5>)> t1.stop()> t1.join()>

array lägga till element java
>

>

Notera: Ovanstående metoder kanske inte fungerar i en eller annan situation, eftersom python inte tillhandahåller någon direkt metod för att döda trådar.