麻豆黑色丝袜jk制服福利网站-麻豆精品传媒视频观看-麻豆精品传媒一二三区在线视频-麻豆精选传媒4区2021-在线视频99-在线视频a

千鋒教育-做有情懷、有良心、有品質的職業教育機構

手機站
千鋒教育

千鋒學習站 | 隨時隨地免費學

千鋒教育

掃一掃進入千鋒手機站

領取全套視頻
千鋒教育

關注千鋒學習站小程序
隨時隨地免費學習課程

當前位置:首頁  >  技術干貨  > 如何殺死一個Python線程

如何殺死一個Python線程

來源:千鋒教育
發布人:xqq
時間: 2023-11-07 02:56:44 1699297004

我經常被問到如何殺死一個后臺線程,這個問題的答案讓很多人不開心:線程是殺不死的。在本文中,我將向您展示Python中用于終止線程的兩個選項。

如果我們是一個好奇寶寶的話,可能會遇到這樣一個問題,就是:如何殺死一個Python的后臺線程呢?我們可能嘗試解決這個問題,卻發現線程是殺不死的。而本文中將展示,在Python中用于終止線程的兩個方式。

1.線程無法結束

·AThreadedExample

下面是一個簡單的,多線程的示例代碼。

importrandom

importthreading

importtime

defbg_thread():

foriinrange(1,30):

print(f'{i}of30iterations...')

time.sleep(random.random())#dosomework...

print(f'{i}iterationscompletedbeforeexiting.')

th=threading.Thread(target=bg_thread)

th.start()

th.join()

使用下面命令來運行程序,在下面的程序運行中,當跑到第7次迭代時,按下Ctrl-C來中斷程序,發現后臺運行的程序并沒有終止掉。而在第13次迭代時,再次按下Ctrl-C來中斷程序,發現程序真的退出了。

$pythonthread.py

1of30iterations...

2of30iterations...

3of30iterations...

4of30iterations...

5of30iterations...

6of30iterations...

7of30iterations...

^CTraceback(mostrecentcalllast):

File"thread.py",line14,in

th.join()

File"/Users/mgrinberg/.pyenv/versions/3.8.6/lib/python3.8/threading.py",line1011,injoin

self._wait_for_tstate_lock()

File"/Users/mgrinberg/.pyenv/versions/3.8.6/lib/python3.8/threading.py",line1027,in_wait_for_tstate_lock

eliflock.acquire(block,timeout):

KeyboardInterrupt

8of30iterations...

9of30iterations...

10of30iterations...

11of30iterations...

12of30iterations...

13of30iterations...

^CExceptionignoredin:

Traceback(mostrecentcalllast):

File"/Users/mgrinberg/.pyenv/versions/3.8.6/lib/python3.8/threading.py",line1388,in_shutdown

lock.acquire()

KeyboardInterrupt:

這很奇怪,不是嗎?究其原因是,Python有一些邏輯是會在進程退出前運行的,專門用來等待任何沒有被配置為守護線程的后臺線程結束,然后再把控制權真正交給操作系統。因此,該進程在其主線程運行時收到到了中斷信號,并準備退出。首先,它需要等待后臺線程運行結束。但是,這個線程對中斷一無所知,這個線程只知道它需要在運行結束前完成30次迭代。

Python在退出過程中使用的等待機制有一個規定,當收到第二個中斷信號時,就會中止。這就是為什么第二個Ctrl-C會立即結束進程。所以我們看到了,線程是不能被殺死!在下面的章節中,將向展示Python中的兩個方式,來使線程及時結束。

2.使用守護進程

·DaemonThreads

在上面提到過,在Python退出之前,它會等待任何非守護線程的線程。而守護線程就是,一個不會阻止Python解釋器退出的線程。

如何使一個線程成為一個守護線程?所有的線程對象都有一個daemon屬性,可以在啟動線程之前將這個屬性設置為True,然后該線程就會被視為一個守護線程。下面是上面的示例應用程序,修改后守護線程版本:

importrandom

importthreading

importtime

defbg_thread():

foriinrange(1,30):

print(f'{i}of30iterations...')

time.sleep(random.random())#dosomework...

print(f'{i}iterationscompletedbeforeexiting.')

th=threading.Thread(target=bg_thread)

th.daemon=True

th.start()

th.join()

再次運行它,并嘗試中斷它,發現第一個執行Ctrl-C后進程立即就退出了。

~$pythonx.py

1of30iterations...

2of30iterations...

3of30iterations...

4of30iterations...

5of30iterations...

6of30iterations...

^CTraceback(mostrecentcalllast):

File"thread.py",line15,in

th.join()

File"/Users/mgrinberg/.pyenv/versions/3.8.6/lib/python3.8/threading.py",line1011,injoin

self._wait_for_tstate_lock()

File"/Users/mgrinberg/.pyenv/versions/3.8.6/lib/python3.8/threading.py",line1027,in_wait_for_tstate_lock

eliflock.acquire(block,timeout):

KeyboardInterrupt

那么這個線程會發生什么呢?線程繼續運行,就像什么都沒發生一樣,直到Python進程終止并返回到操作系統。這時,線程就不存在了。你可能認為這實際上是一種殺死線程的方法,但要考慮到以這種方式殺死線程,你必須同時殺死進程。

3.使用事件對象

·PythonEvents

使用守護線程,是一種避免在多線程程序中處理意外中斷的簡單方法,但這是一種只在進程退出的特殊情況下才有效的技巧。不幸的是,有些時候,一個應用程序可能想結束一個線程而不必殺死自己。另外,有些線程可能需要在退出前執行清理工作,而守護線程則不允許這樣操作。

那么,還有什么其他選擇呢?既然不可能強制線程結束,那么唯一的選擇就是給它添加邏輯,讓它在被要求退出時自愿退出。有多種方法都可以解決上述問題,但我特別喜歡的一種方法,就是使用一個Event對象。

Event類是由Python標準庫的線程模塊提供,你可以通過實例化類來創建一個事件對象,就像下面這個樣子:

exit_event=threading.Event()

Event對象可以處于兩種狀態之一:set或notset。當我們實例化創建之后,默認事件并沒有被設置。

·若要將事件狀態更改為set,則可以調用set()方法;

·要查明是否設置了事件,使用is_set()方法,設置了則返回True;

·還可以使用wait()方法等待事件,等待操作阻塞直到設置事件(可以設置超時)

其核心思路,就是在線程需要退出的時候設置事件。然后,線程需要經常地檢查事件的狀態(通常是在循環中),并在發現事件已經設置時處理自己的終止。對于上面顯示的示例,一個好的解決方案是添加一個捕獲Ctrl-C中斷的信號處理程序,而不是突然退出,只需設置事件并讓線程優雅地結束。

importrandom

importsignal

importthreading

importtime

exit_event=threading.Event()

defbg_thread():

foriinrange(1,30):

print(f'{i}of30iterations...')

time.sleep(random.random())#dosomework...

ifexit_event.is_set():

break

print(f'{i}iterationscompletedbeforeexiting.')

defsignal_handler(signum,frame):

exit_event.set()

signal.signal(signal.SIGINT,signal_handler)

th=threading.Thread(target=bg_thread)

th.start()

th.join()

如果你嘗試中斷這個版本的應用程序,一切看起來都會更好:

$pythonthread.py

1of30iterations...

2of30iterations...

3of30iterations...

4of30iterations...

5of30iterations...

6of30iterations...

7of30iterations...

^C7iterationscompletedbeforeexiting.

需要注意的是,中斷是如何被優雅地處理的,以及線程能夠運行在循環之后出現的代碼。如果當線程需要在退出之前,關閉文件句柄或數據庫連接時,這種方式就非常有用了。其能夠在線程退出之前,運行清理代碼有時是必要的,以避免資源泄漏。我在上面提到過,event對象也是可以等待的:

foriinrange(1,30):

print(f'{i}of30iterations...')

time.sleep(random.random())

ifexit_event.is_set():

break

在每個迭代中,都有一個對time.sleep()的調用,這將阻塞線程。如果在線程sleep時設置了退出事件,那么它就不能檢查事件的狀態,因此在線程能夠退出之前會有一個小的延遲。在這種情況下,如果有sleep,使用wait()方法將sleep與event對象的檢查結合起來會更有效:

foriinrange(1,30):

print(f'{i}of30iterations...')

ifexit_event.wait(timeout=random.random()):

break

這個解決方案有效地為提供了一個可中斷的sleep,因為在線程停留在wait()調用的中間時設置了事件,那么等待將立即返回。

4.總結陳述說明

·Conclusion

你知道Python中的event對象嗎?它們是比較簡單的同步原語之一,不僅可以用作退出信號,而且在線程需要等待某些外部條件發生的許多其他情況下也可以使用。

以上內容為大家介紹了如何殺死一個Python線程,希望對大家有所幫助,如果想要了解更多Python相關知識,請關注IT培訓機構:千鋒教育。http://www.dietsnews.net/

tags: python培訓
聲明:本站稿件版權均屬千鋒教育所有,未經許可不得擅自轉載。
10年以上業內強師集結,手把手帶你蛻變精英
請您保持通訊暢通,專屬學習老師24小時內將與您1V1溝通
免費領取
今日已有369人領取成功
劉同學 138****2860 剛剛成功領取
王同學 131****2015 剛剛成功領取
張同學 133****4652 剛剛成功領取
李同學 135****8607 剛剛成功領取
楊同學 132****5667 剛剛成功領取
岳同學 134****6652 剛剛成功領取
梁同學 157****2950 剛剛成功領取
劉同學 189****1015 剛剛成功領取
張同學 155****4678 剛剛成功領取
鄒同學 139****2907 剛剛成功領取
董同學 138****2867 剛剛成功領取
周同學 136****3602 剛剛成功領取
相關推薦HOT
主站蜘蛛池模板: 日韩孕交| 免费看男阳茎进女阳道动态图| 免费高清a级毛片在线播放| 欧美日韩欧美| 久久蜜桃| 中文字幕在线电影| 亚洲免费网址| 久久综合伊人| 黄色大片在线视频| 一本之道久久| 啊灬啊别停灬用力啊岳| 菠萝蜜视频在线观看入口| 天堂网欧美| 在线www| 大学生男男澡堂69gaysex| 2019天天干夜夜操| 三级极精品电影| 美女主动张腿让男人桶| 国产综合久久久久| 韩国理论电影午夜三级717| 欧美黑人巨大videos极品| 免费无毒片在线观看| 国产四虎精品| 网曝门精品国产事件在线观看| 精品一区二区三区3d动漫 | 欧美日韩无线码在线观看| 草草影院国产| 高h视频网站| 又粗又大又猛又爽免费视频| 午夜一级毛片| 最新国产精品亚洲| 波多野结衣在线女教师| 欧美巨大黑人hd| 97精品伊人久久大香线蕉| 波多野结衣厨房被强电影| 中国speakingathome宾馆学生| 欧美精品寂寞影院请用uc| 97色伦图片97综合影院| 8888四色奇米在线观看免费看 | 欧美日韩中文字幕在线视频| 国产三级在线观看专区|