python隨筆小題-一場針對執行緒的謀殺案
話說上次大佬(@天元浪子)發新書開直播的時候前去支援了一波,在直播中有一道題目很有意思:
嘗試給一個input函式計時,如果使用者在十秒內輸入引數則顯示引數,超過十秒那就關閉輸入渠道,或者乾脆說就不讓輸了。
嗯…一看到十秒倒計時那第一反應就是time模組了(廢話)。得,先寫上唄。
import time
那接下來就是比較麻煩的一個情況,我既需要程式一邊檢測並等待使用者藉助input輸入字元,另一方面還需要程式自己給自己掐一個10秒鐘的秒錶,唉?!多程序?!
那來唄,import走起!
import multiprocessing
然後嘗試寫了兩個函式,一個是顯示input輸入:
def action ():
"""使用者輸入模組"""
s = input('輸入引數:')
print(s)
另一個就掐時間唄:
def timeOut():
"""殺死程序模組"""
time.sleep(10)
"""此處等待殺死上面那個函式嘿嘿嘿"""
然後就是考慮A程序啟動後得到一個程序編號(PID),然後B程序拿到這個程序編號開始計時,時間一到,按照這個編號幹它:
import multiprocessing
import os
import time
def action():
"""使用者輸入模組"""
s = input('輸入引數:')
print(s)
def timeOut():
"""殺死程序模組"""
time.sleep(10)
"""此處等待殺死上面那個函式嘿嘿嘿"""
os.popen('taskkill.exe /pid:' + str(os.getppid( )))
"""需要說明一下,為了省事,我也不拿另一個程序的pid了,直接穩賺狠拿了父程序pid,一窩端"""
if __name__ == '__main__':
mp1 = multiprocessing.Process(target=action)
mp1.start()
mp2 = multiprocessing.Process(target=timeOut)
mp2.start()
啪一下就寫完了,很快啊!執行!!!
啪嘰!!!
艹(一種植物)!!!!怎麼這麼紅?!
原來!!!
程序不支援input函式!!!
不支援input函式!!!
input函式!!!
函式!!!
嗯…
嘿嘿嘿我是傻子嘿嘿嘿…
——————————————————————————————————————
吃完藥之後,我決定換個方式,程序拉倒,那就執行緒:
import threading
早知道一開始就用執行緒了,你看這個模組名字就短不少(誤)。
但是問題是,執行緒間不能通訊,那我怎麼才能讓一個執行緒到點了把另一個執行緒帶走呢???
那就是————開守護執行緒!
守護執行緒這名字聽著高大上,其實說白了,就是給某個或者某些執行緒加個daemon引數。
你比如說t1是個執行緒,那隻要在開始這個執行緒之前,這樣子:
t1.daemon = True
那這個執行緒就是守護執行緒了。
那這個執行緒開了守護能幹啥呢,你可以這麼理解:
比如一個程式由多個執行緒組成,那麼程式整體結束的標準是參照所有【非守護】執行緒是否結束。換句話說,當所有【非守護】執行緒結束的時候,程式就直接啪嘰結束了,那些還在執行的守護執行緒咋辦呢,直接強行結束。
…名字好聽,還守護執行緒,就是備胎執行緒唄。
奇怪,我怎麼突然就悟了???
——————————————————————————————————————
哭完之後,把這個程式寫出來了:
import threading
import time
def action():
s = input('輸入引數>>> ')
print(s)
def timeOut():
time.sleep(10)
print('time out!')
if __name__ == '__main__':
t1 = threading.Thread(target=action)
t2 = threading.Thread(target=timeOut)
t1.daemon = True
t1.start()
t2.start()
本來故事到這裡就能結束了,上面這個答案也能算得上是一個標準答案。
但是
備胎這個詞不好(明明叫守護!),而且既然整個程式就倆執行緒,那麼只要在倒計時結束的時候直接強行拉閘,那什麼執行緒都要玩完,本著完(bu)美(dang)結(bei)局(tai)的想法,考慮了一下如何才能直接用python關閉當前整個程式,艾?還真可以:
import os
於是,暴力拉閘版本就整出來了:
import threading
import time
import os
def action():
s = input('輸入引數>>> ')
print(s)
def timeOut():
time.sleep(10)
print('time out!')
os._exit(0)
if __name__ == '__main__':
t1 = threading.Thread(target=action)
t2 = threading.Thread(target=timeOut)
t1.start()
t2.start()