Apskritai, staigus gijų žudymas laikomas bloga programavimo praktika. Staiga nutraukus giją gali likti svarbus šaltinis, kuris turi būti tinkamai uždarytas, atidarytas. Tačiau galbūt norėsite nutraukti giją, kai praeis konkretus laikotarpis arba bus sugeneruotas pertraukimas. Yra įvairių metodų, kuriais galite nužudyti giją „Python“.
- Išimčių kėlimas python gijoje
- Nustatyti / iš naujo nustatyti sustabdymo vėliavėlę
- Pėdsakų naudojimas gijų naikinimui
- Kelių apdorojimo modulio naudojimas gijų naikinimui
- „Python“ gijos sunaikinimas nustatant jį kaip demoną
- Naudojant paslėptą funkciją _stop()
Išimčių iškėlimas python gijoje:
Šis metodas naudoja funkciją PyThreadState_SetAsyncExc() iškelti išimtį a gijoje. Pavyzdžiui,
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()> |
>
>
Kai paleidžiame aukščiau pateiktą kodą mašinoje ir pastebėsite, kad kai tik iškviečiama funkcija raise_exception(), tikslinė funkcija run() baigiasi. Taip yra todėl, kad kai tik iškeliama išimtis, programos valdymas iššoka iš trynimo bloko ir funkcija run() nutraukiama. Po to join() funkcija gali būti iškviesta, kad užmuštų giją. Jei nėra funkcijos run_exception(), tikslinė funkcija run() veikia amžinai, o funkcija join() niekada nėra iškviečiama, kad būtų užmušta gija.
Nustatyti / iš naujo nustatyti sustabdymo vėliavėlę:
Norėdami sunaikinti giją, galime paskelbti sustabdymo vėliavėlę ir ši vėliavėlė retkarčiais bus patikrinta pagal giją. Pavyzdžiui
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'>)> |
>
>
Pirmiau pateiktame kode, kai tik nustatomas visuotinis kintamasis stop_threads, tikslinė funkcija run() baigiasi ir giją t1 galima užmušti naudojant t1.join(). Tačiau dėl tam tikrų priežasčių galima susilaikyti nuo visuotinio kintamojo naudojimo. Tokiose situacijose funkcijų objektai gali būti perduoti, kad būtų teikiamos panašios funkcijos, kaip parodyta toliau.
Python3
kas yra gb
# 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()> |
>
>
Aukščiau pateiktame kode perduotas funkcijos objektas visada grąžina vietinio kintamojo stop_threads reikšmę. Ši reikšmė tikrinama funkcijoje run(), o kai tik stop_threads atstatomas, funkcija run() baigiasi ir gija gali būti užmušta.
Pėdsakų naudojimas gijų naikinimui:
Šis metodas veikia įdiegiant pėdsakų kiekvienoje gijoje. Kiekvienas pėdsakas baigiasi aptikęs kokį nors stimulą ar vėliavėlę, taip akimirksniu užmušdamas susijusią giją. Pavyzdžiui
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'>)> |
>
>
Šiame kode start() yra šiek tiek pakeistas, kad būtų nustatyta sistemos sekimo funkcija naudojant settrace () . Vietinė sekimo funkcija apibrėžiama taip, kad, kai nustatoma atitinkamos gijos žudymo vėliavėlė (killed), vykdant kitą kodo eilutę iškeliama SystemExit išimtis, kuri užbaigia tikslinės funkcijos func vykdymą. Dabar giją galima užmušti naudojant join().
Kelių apdorojimo modulio naudojimas gijų naikinimui:
Daugiafunkcinis Python modulis leidžia sukurti procesus taip, kaip sukuriate gijas naudojant gijų modulį. Daugiasriegio modulio sąsaja yra panaši į sriegimo modulio sąsają. Pavyzdžiui, tam tikrame kode sukūrėme tris gijas (procesus), kurios skaičiuojamos nuo 1 iki 9.
Python3
pagrindinė java kalba
# 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()> |
>
>
Aukščiau pateikto kodo funkcionalumas taip pat gali būti įgyvendintas naudojant kelių apdorojimo modulį panašiai, su labai mažais pakeitimais. Žiūrėkite žemiau pateiktą kodą.
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()> |
>
>
Nors abiejų modulių sąsaja yra panaši, abu moduliai turi labai skirtingą įgyvendinimą. Visos gijos turi pasaulinius kintamuosius, o procesai yra visiškai atskirti vienas nuo kito. Taigi, žudymo procesai yra daug saugesni, palyginti su žudymo siūlais. Proceso klasėje pateikiamas metodas, nutraukti () , nužudyti procesą. Dabar grįžkime prie pradinės problemos. Tarkime, kad aukščiau pateiktame kode norime užmušti visus procesus praėjus 0.03 s. Ši funkcija pasiekiama naudojant kelių apdorojimo modulį šiame kode.
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()> |
>
>
Nors abu moduliai turi skirtingą įgyvendinimą. Ši funkcija, kurią teikia kelių apdorojimo modulis aukščiau pateiktame kode, yra panaši į gijų naikinimą. Taigi kelių apdorojimo modulis gali būti naudojamas kaip paprastas alternatyva kai iš mūsų reikalaujama įdiegti gijų naikinimą Python.
„Python“ gijos sunaikinimas nustatant ją kaip demoną:
Demonų gijos yra tos gijos, kurios užmušamos, kai pagrindinė programa išeina. Pavyzdžiui
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()> |
>
>
Atkreipkite dėmesį, kad gija t1 išlieka gyva ir neleidžia pagrindinei programai išeiti per sys.exit(). „Python“ programoje bet kuri gyva ne demono gija blokuoja pagrindinę programą, kad ji galėtų išeiti. Tuo tarpu pačios demonų gijos žūva, kai tik išeina pagrindinė programa. Kitaip tariant, kai tik pagrindinė programa išeina, visos demono gijos yra nužudomos. Norėdami paskelbti giją kaip demoną, raktinio žodžio argumentą demonas nustatome kaip True. Pavyzdžiui, pateiktame kode jis parodo demonų gijų savybę.
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()> |
>
>
Atkreipkite dėmesį, kad kai tik pagrindinė programa išeina, t1 gija užmušama. Šis metodas pasirodė esąs labai naudingas tais atvejais, kai programos nutraukimas gali būti naudojamas gijų sunaikinimui sukelti. Atminkite, kad „Python“ programoje pagrindinė programa baigiasi, kai tik visos ne demono gijos yra mirusios, nepaisant gyvų demonų gijų skaičiaus. Taigi šių demonų gijų turimi ištekliai, pvz., atidaryti failai, duomenų bazės operacijos ir kt., gali būti netinkamai išleisti. Pradinė valdymo gija python programoje nėra demono gija. Nerekomenduojama priverstinai naikinti siūlą, nebent tiksliai žinoma, kad tai nesukels jokių nutekėjimų ar aklavietės.
Naudojant paslėptą funkciją _stop() :
Norėdami sunaikinti giją, naudojame paslėptą funkciją _stop() ši funkcija nėra dokumentuota, bet gali išnykti kitoje python versijoje.
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()> |
sql ddl komandas
>
>
Pastaba: Aukščiau pateikti metodai gali neveikti tam tikroje ar kitoje situacijoje, nes python nepateikia jokio tiesioginio metodo gijų naikinimui.