我有一個Python多處理應用程序,它啓動使用多處理API的「工作人員」。主進程本身是由一個不用Python編寫的服務進程啓動的。工作人員可能會使用subprocess.Popen
開始其他非Python子流程。Python子進程阻止在主進程中阻止從標準輸入讀取
爲了清楚起見,這是整個過程的層次結構:
- service.exe:服務過程(天然EXE)
- python.exe:Python的主處理(以下程序)
- 蟒.exe:Python子進程(任務函數由進程啓動)
- subprocess.exe:本機子進程(請參閱下面的說明)
- 蟒.exe:Python子進程(任務函數由進程啓動)
- python.exe:Python的主處理(以下程序)
當服務過程停止,它必須告訴Python的進程退出。我正在使用標準輸入。好處是,如果服務進程崩潰或被終止,那麼Python進程的標準輸入就會關閉,所以它將退出,並且不會有孤立進程。
import multiprocessing
import time
import sys
def task():
print("Task started...")
# TODO: Start a native process here using Subprocess.popen
time.sleep(3)
print("Task ended")
if __name__ == '__main__':
process = multiprocessing.Process(target=task)
process.start()
# time.sleep(3) # "workaround"
sys.stdin.read()
print("Terminating process...")
process.terminate()
然而,似乎當我添加sys.stdin.read()
,Python的子進程啓動,但它不會做任何事情。它似乎掛起。
(壞)解決方法是在從標準輸入讀取之前添加time.sleep(3)
。然後上面的程序工作。但是,似乎Python子進程啓動的子進程仍然可以阻塞,只有在主進程中執行阻塞讀取時,它們纔會阻塞。
在所有系統上都不會發生此問題。它在一臺Windows 8機器上被觀察到,並且從未在另一臺Windows機器上發生過。我正在使用Python 2.7.2。
我的問題是:如何在主進程中的阻塞讀取影響子進程?子過程不應該獨立於我在主過程中做的任何事情而開始和運行嗎? (我只想了解這個問題,如果你找到一個更好的解決方案來停止服務進程中的Python進程,我會很感激,但這是奇怪的阻止行爲,給我做惡夢)
在我的真實應用程序中(上面的代碼只是一個簡單的測試程序,我希望能夠重現該問題),子進程寫入數據庫以將「作業」標記爲「進行中」。當且僅當主進程阻止從標準輸入讀取時,纔會發生這種情況。 但是,我同意上述示例可能不會重現實際問題,或者出於其他原因可能無法打印「任務已結束」。 我也忘了提及一位同事無法在他的機器上重現問題。如果我找到時間,我會嘗試使用示例程序的調試技巧... – 2014-09-10 20:03:32
您在您的問題中提出的假設是正確的:從主標準輸入讀取的阻止讀取應該對您的子流程執行沒有影響。嘗試添加幾個文本文件寫入到您的子過程中,您將添加用於調試的打印語句的相同方式,並嘗試縮小子流程的掛起位置。如果您無法用他們提供的信息解決問題,請嘗試在問題中添加一些真實的代碼。看看你是如何啓動子過程以及任務函數中的所有內容(包括掛起的語句)將會很有幫助。 – skrrgwasme 2014-09-10 20:08:05
@FlorianWinter你在使用什麼樣的數據庫?本機支持的數據庫之一?在沒有看到任何與數據庫相關的代碼的情況下,我會建議檢查以確保您的主進程在等待stdin時不保存任何數據庫資源,並確保您的子進程修改數據庫的方式是線程安全的。如果兩個子進程之間發生衝突,這兩個進程都試圖同時修改數據庫,則可能是數據丟失或死鎖。 – skrrgwasme 2014-09-13 17:44:56