logo

Python | Dažādi veidi, kā nogalināt pavedienu

Kopumā pēkšņa pavedienu nogalināšana tiek uzskatīta par sliktu programmēšanas praksi. Pēkšņa pavediena nogalināšana var atstāt kritisku resursu, kas ir pareizi jāaizver, jāatver. Bet jūs varētu vēlēties pārtraukt pavedienu, kad ir pagājis noteikts laika periods vai ir ģenerēts pārtraukums. Ir dažādas metodes, ar kurām jūs varat nogalināt pavedienu programmā python.

  • Izņēmumu izvirzīšana python pavedienā
  • Iestatīt/atiestatīt apstāšanās karogu
  • Izmantojot pēdas, lai iznīcinātu pavedienus
  • Daudzapstrādes moduļa izmantošana, lai iznīcinātu pavedienus
  • Python pavediena nogalināšana, iestatot to kā dēmonu
  • Izmantojot slēpto funkciju _stop()

Izņēmumu izvirzīšana python pavedienā:
Šī metode izmanto funkciju PyThreadState_SetAsyncExc() lai izvirzītu izņēmumu pavedienā. Piemēram,



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

>

>

Palaižot iepriekš minēto kodu mašīnā un jūs ievērosiet, ka, tiklīdz tiek izsaukta funkcija raise_exception(), mērķa funkcija run() beidzas. Tas ir tāpēc, ka, tiklīdz tiek izvirzīts izņēmums, programmas vadība izlec no mēģinājuma bloka un funkcija palaist () tiek pārtraukta. Pēc tam var izsaukt funkciju join(), lai iznīcinātu pavedienu. Ja nav funkcijas run_exception(), mērķa funkcija run() turpina darboties mūžīgi, un funkcija join() nekad netiek izsaukta, lai iznīcinātu pavedienu.

Iestatīt/atiestatīt apstāšanās karogu:
Lai iznīcinātu pavedienu, mēs varam paziņot par apturēšanas karogu, un šis karogs periodiski tiks pārbaudīts ar pavedienu. Piemēram

Python3




# 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'>)>

>

>

Iepriekš minētajā kodā, tiklīdz ir iestatīts globālais mainīgais stop_threads, mērķa funkcija run() beidzas un pavedienu t1 var iznīcināt, izmantojot t1.join(). Taču noteiktu iemeslu dēļ var atturēties no globālā mainīgā izmantošanas. Šādās situācijās funkciju objektus var nodot, lai nodrošinātu līdzīgu funkcionalitāti, kā parādīts tālāk.

Python3


verilog parametrs



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

>

>

Iepriekš minētajā kodā nodotais funkcijas objekts vienmēr atgriež vietējā mainīgā stop_threads vērtību. Šī vērtība tiek pārbaudīta funkcijā run (), un, tiklīdz stop_threads ir atiestatīts, funkcija run () beidzas un pavediens var tikt iznīcināts.

Trases izmantošana pavedienu iznīcināšanai:
Šīs metodes darbojas, instalējot pēdas katrā pavedienā. Katra pēda beidzas, atklājot kādu stimulu vai karogu, tādējādi uzreiz nogalinot saistīto pavedienu. Piemēram

Python3


alfa beta atzarošanas piemērs



# 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'>)>

>

>

Šajā kodā start() ir nedaudz modificēts, lai iestatītu sistēmas izsekošanas funkciju, izmantojot settrace() . Vietējā izsekošanas funkcija ir definēta tā, ka ikreiz, kad ir iestatīts attiecīgā pavediena nogalināšanas karogs (killed), tiek parādīts SystemExit izņēmums, izpildot nākamo koda rindu, kas beidz mērķa funkcijas funkcijas izpildi. Tagad pavedienu var iznīcināt ar join().

Vairāku apstrādes moduļa izmantošana pavedienu likvidēšanai:
Python daudzapstrādes modulis ļauj izveidot procesus tādā pašā veidā, kā veidojat pavedienus, izmantojot pavedienu moduli. Daudzpavedienu moduļa saskarne ir līdzīga vītņu moduļa saskarnei. Piemēram, dotajā kodā mēs izveidojām trīs pavedienus (procesus), kuru skaits ir no 1 līdz 9.

Python3




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

>

>

Iepriekš minētā koda funkcionalitāti var īstenot arī, izmantojot vairāku apstrādes moduli līdzīgā veidā, ar ļoti nelielām izmaiņām. Skatiet tālāk norādīto kodu.

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

>

>

Lai gan abu moduļu saskarne ir līdzīga, abiem moduļiem ir ļoti atšķirīgas ieviešanas. Visiem pavedieniem ir kopīgi globālie mainīgie, turpretim procesi ir pilnīgi atsevišķi viens no otra. Tādējādi nogalināšanas procesi ir daudz drošāki, salīdzinot ar pavedienu nogalināšanu. Klasei Process tiek nodrošināta metode, pārtraukt () , lai nogalinātu procesu. Tagad atgriežoties pie sākotnējās problēmas. Pieņemsim, ka iepriekš minētajā kodā mēs vēlamies iznīcināt visus procesus pēc 0,03 s. Šī funkcionalitāte tiek panākta, izmantojot daudzapstrādes moduli šādā 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()>

>

>

Lai gan abiem moduļiem ir dažādas ieviešanas. Šī funkcionalitāte, ko nodrošina vairāku apstrādes modulis iepriekš minētajā kodā, ir līdzīga pavedienu nogalināšanai. Tādējādi daudzapstrādes moduli var izmantot kā vienkāršu alternatīva ikreiz, kad mums Python ir jāievieš pavedienu nogalināšana.

Python pavediena nogalināšana, iestatot to kā dēmonu:
Dēmonu pavedieni ir tie pavedieni, kas tiek iznīcināti, kad galvenā programma iziet. Piemēram

Python3

Oracle sql nav vienāds




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

>

>

Ņemiet vērā, ka pavediens t1 paliek dzīvs un neļauj galvenajai programmai iziet, izmantojot sys.exit(). Programmā Python jebkurš dzīvs pavediens, kas nav dēmons, bloķē galveno programmu, lai tā izietu. Savukārt paši dēmonu pavedieni tiek iznīcināti, tiklīdz galvenā programma iziet. Citiem vārdiem sakot, tiklīdz galvenā programma iziet, visi dēmonu pavedieni tiek iznīcināti. Lai pavedienu pasludinātu par dēmonu, mēs iestatām atslēgvārda argumentu dēmonu kā True. Piemēram, dotajā kodā tas parāda dēmonu pavedienu īpašības.

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

>

>

Ievērojiet, ka, tiklīdz galvenā programma iziet, pavediens t1 tiek iznīcināts. Šī metode izrādās ļoti noderīga gadījumos, kad programmas pārtraukšanu var izmantot, lai izraisītu pavedienu nogalināšanu. Ņemiet vērā, ka programmā Python galvenā programma tiek pārtraukta, tiklīdz visi bezdēmonu pavedieni ir miruši, neatkarīgi no dzīvo dēmonu pavedienu skaita. Tādējādi šo dēmonu pavedienu resursi, piemēram, atvērtie faili, datu bāzes transakcijas utt., var netikt atbrīvoti pareizi. Sākotnējais vadības pavediens Python programmā nav dēmona pavediens. Vītnes piespiedu nogalināšana nav ieteicama, ja vien nav droši zināms, ka tas neizraisīs noplūdes vai strupceļus.
Izmantojot slēpto funkciju _stop() :
Lai iznīcinātu pavedienu, mēs izmantojam slēpto funkciju _stop(), šī funkcija nav dokumentēta, taču nākamajā python versijā tā var pazust.

aizvietot java virknē

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

>

>

Piezīme: Iepriekš minētās metodes var nedarboties kādā vai citā situācijā, jo python nenodrošina tiešu metodi pavedienu iznīcināšanai.