我想在其中一個子行程到達特定點時結束我的腳本。假設我有以下代碼:
import multiprocessing
import time
import sys
def another_child_process (my_queue):
time.sleep(3)
my_queue.put("finish")
def my_process(my_queue):
while True:
if my_queue.empty() is False:
my_queue.get()
print("Killing the program...")
### THIS IS WHERE I WANT TO KILL MAIN PROCESS AND EXIT
sys.exit(0)
def main():
## PARENT PROCESS WHICH I WANT TO KILL FROM THE CHILD
my_queue = multiprocessing.Queue()
child_process = multiprocessing.Process(target=my_process, args=(my_queue,))
another_process = multiprocessing.Process(target=another_child_process, args=(my_queue,))
child_process.start()
another_process.start()
while True:
pass ## I want to end the program in the child process
if __name__=="__main__":
main()
我讀過一些關于使用信號的東西,但它們主要用于 Linux,我不太清楚如何在 Windows 中使用它們。實際上,我是 Python 的初學者。我怎樣才能完全結束腳本?非常感謝您抽出寶貴時間
uj5u.com熱心網友回復:
首先,如果你仔細閱讀檔案,你會發現is_empty在 a上調??用方法multiprocessing.Queue是不可靠的,不應該使用。此外,你有一個競爭條件。也就是說,如果my_process之前運行another_child_process(并且假設is_empty是可靠的),它將發現佇列為空并提前終止,因為another_child_process還沒有機會將任何專案放入佇列。所以你應該做的是another_child_process將它想要的任何訊息放在佇列中,然后放置一個額外的哨兵專案,其目的是表明沒有更多的專案將被放入佇列。因此,哨兵用作準檔案結束指示器。您可以使用任何不同的物件作為哨兵,只要它不能被視為“真實”資料項。在這種情況下,我們將None用作哨兵。
但是您撰寫的實際示例并不是一個實際示例,說明為什么您需要一些特殊機制來終止主行程并退出,因為一旦another_process將其專案放入佇列,它就會回傳,因此行程終止并且一旦my_process檢測到它有從佇列中檢索所有專案并且將不再有,它回傳并因此其行程終止。因此,主行程所要做的就是join對兩個子行程發出呼叫并等待它們完成然后退出:
import multiprocessing
import time
import sys
def another_child_process (my_queue):
time.sleep(3)
my_queue.put("finish")
my_queue.put(None)
def my_process(my_queue):
while True:
item = my_queue.get()
if item is None:
break
print('Item:', item)
def main():
## PARENT PROCESS WHICH I WANT TO KILL FROM THE CHILD
my_queue = multiprocessing.Queue()
child_process = multiprocessing.Process(target=my_process, args=(my_queue,))
another_process = multiprocessing.Process(target=another_child_process, args=(my_queue,))
child_process.start()
another_process.start()
child_process.join()
another_process.join()
if __name__=="__main__":
main()
印刷:
Item: finish
這里也許是一個更好的例子。another_child_process以某種方式獲取資料(出于演示目的,我們有一個生成器函式,get_data)。如果沒有出現例外情況,它會將所有資料放入佇列中,my_process以便被None哨兵專案跟蹤,這樣就my_process知道沒有更多的資料即將到來,它可以終止。但是讓我們假設有可能get_data產生一個特殊的、例外的資料項,即用于演示目的的字串“finish”。在這種情況下another_child_process將立即終止。然而,此時佇列中my_process有許多專案尚未檢索和處理。我們想強制my_process立即終止,以便主行程可以立即join子行程并終止。
為此,我們將一個事件傳遞給由主行程啟動的守護執行緒,該執行緒等待事件被設定。如果事件是由 設定的another_child_process,我們也將事件傳遞給了它,執行緒將立即終止my_process行程:
import multiprocessing
import time
import sys
def get_data():
for item in ['a', 'b', 'c', 'finish', 'd', 'e', 'f', 'g']:
yield item
def another_child_process(my_queue, exit_event):
for item in get_data():
if item == 'finish':
# Abnormal condition where we must exit imemediately.
# Immediately signal main process terminate:
exit_event.set()
# And we terminate:
return
my_queue.put(item)
# Normal situation where we just continue
# Put in sentinel signifying no more data:
my_queue.put(None)
def my_process(my_queue):
while True:
item = my_queue.get()
if item is None: # Sentinel?
# No more data:
break
print("Got: ", repr(item))
print('my_process terminating normally.')
def main():
import threading
def wait_for_quit(exit_event):
nonlocal child_process
exit_event.wait()
child_process.terminate()
print("Exiting because event was set.")
exit_event = multiprocessing.Event()
# Start daemon thread that will wait for the quit_event
threading.Thread(target=wait_for_quit, args=(exit_event,), daemon=True).start()
my_queue = multiprocessing.Queue()
child_process = multiprocessing.Process(target=my_process, args=(my_queue,))
another_process = multiprocessing.Process(target=another_child_process, args=(my_queue, exit_event))
child_process.start()
another_process.start()
# Wait for processes to end:
child_process.join()
another_process.join()
if __name__=="__main__":
main()
印刷:
Got: 'a'
Exiting because event was set.
如果您finish從回傳的資料中洗掉訊息get_data,則所有行程將正常完成,列印的內容將是:
Got: 'a'
Got: 'b'
Got: 'c'
Got: 'd'
Got: 'e'
Got: 'f'
Got: 'g'
my_process terminating normally.
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/481167.html
