Ini bisa menjadi pertanyaan yang bodoh, tetapi saya menguji beberapa asumsi saya tentang Python dan saya bingung mengapa potongan kode berikut tidak akan keluar saat dipanggil di utas, tetapi akan keluar saat dipanggil di utas utama.
import sys, time
from threading import Thread
def testexit():
time.sleep(5)
sys.exit()
print "post thread exit"
t = Thread(target = testexit)
t.start()
t.join()
print "pre main exit, post thread exit"
sys.exit()
print "post main exit"
Dokumen untuk sys.exit () menyatakan bahwa panggilan harus keluar dari Python. Saya dapat melihat dari output program ini bahwa "post thread exit" tidak pernah dicetak, tetapi thread utama terus berjalan bahkan setelah thread memanggil keluar.
Apakah instance terpisah dari interpreter sedang dibuat untuk setiap thread, dan panggilan ke exit () hanya keluar dari instance terpisah itu? Jika ya, bagaimana implementasi threading mengelola akses ke sumber daya bersama? Bagaimana jika saya memang ingin keluar dari program dari utas (bukan yang sebenarnya saya inginkan, tetapi supaya saya mengerti)?
sumber
Terlepas dari metode yang dijelaskan Deestan, Anda dapat memanggil
os._exit
(perhatikan garis bawahnya ). Sebelum menggunakannya pastikan bahwa Anda memahami bahwa hal itu tidak ada pembersihan (seperti menelepon__del__
atau serupa).sumber
os._exit
digunakan dalam kutukan konsol tidak diatur ulang ke keadaan normal dengan ini. Anda harus mengeksekusireset
di Unix-shell untuk memperbaikinya.Apakah fakta bahwa "pre main exit, post thread exit" dicetak yang mengganggu Anda?
Tidak seperti beberapa bahasa lain (seperti Java) di mana analog ke
sys.exit
(System.exit
, dalam kasus Java) menyebabkan VM / proses / interpreter segera berhenti, Pythonsys.exit
hanya melontarkan pengecualian: khususnya pengecualian SystemExit.Berikut adalah dokumen untuk
sys.exit
(hanyaprint sys.exit.__doc__
):Ini memiliki beberapa konsekuensi:
__del__
) berpotensi dipanggil saat tumpukan frame yang mereferensikan objek tersebut dibatalkanSystemExit
pengecualianYang terakhir mungkin yang paling mengejutkan, dan merupakan alasan lain mengapa Anda hampir tidak pernah memiliki
except
pernyataan yang tidak memenuhi syarat dalam kode Python Anda.sumber
Metode pilihan saya adalah penyampaian pesan Erlang-ish. Sedikit disederhanakan, saya melakukannya seperti ini:
import sys, time import threading import Queue # thread-safe class CleanExit: pass ipq = Queue.Queue() def testexit(ipq): time.sleep(5) ipq.put(CleanExit) return threading.Thread(target=testexit, args=(ipq,)).start() while True: print "Working..." time.sleep(1) try: if ipq.get_nowait() == CleanExit: sys.exit() except Queue.Empty: pass
sumber
Queue
sini. Sederhanabool
saja sudah cukup. Nama klasik untuk variabel ini adalahis_active
dan nilai default awalnya adalahTrue
.bool
(atau operasi atom lainnya) akan berhasil dengan sempurna untuk masalah khusus ini. Alasan saya pergi denganQueue
s adalah bahwa ketika bekerja dengan agen berulir saya cenderung berakhir membutuhkan beberapa sinyal yang berbeda (flush
,reconnect
,exit
, dll ...) segera.bool
akan berhasil, seperti yang @Acumenus tunjukkan, maka yang sederhana jugaint
akan menjadi satu -satunya yang dibutuhkan untuk dapat menangani beberapa sinyal yang berbeda - bagaimanapunbool
juga, hanyalah subclass dariint
._thread.interrupt_main()
tersedia sejak Python 3.7 (opsional sebelum itu)sumber