[英]Python: How to prevent subprocesses from receiving CTRL-C / Control-C / SIGINT
我目前正在為在 shell 中運行的專用服務器開發包裝器。 包裝器通過子進程生成服務器進程,並觀察其輸出並對其做出反應。
專用服務器必須明確給出命令以正常關閉。 因此,CTRL-C 不能到達服務器進程。
如果我在 python 中捕獲 KeyboardInterrupt 異常或覆蓋 SIGINT 處理程序,服務器進程仍會收到 CTRL-C 並立即停止。
所以我的問題是:如何防止子進程接收 CTRL-C / Control-C / SIGINT?
#python IRC-Channel (Freenode) 中的某個人通過指出subprocess.Popen (...)的preexec_fn參數來幫助我:
如果preexec_fn設置為可調用對象,則該對象將在子進程執行之前在子進程中調用。 (僅限 Unix)
因此,以下代碼解決了該問題(僅限 UNIX):
import subprocess
import signal
def preexec_function():
# Ignore the SIGINT signal by setting the handler to the standard
# signal handler SIG_IGN.
signal.signal(signal.SIGINT, signal.SIG_IGN)
my_process = subprocess.Popen(
["my_executable"],
preexec_fn = preexec_function
)
注意:實際上並沒有阻止信號到達子進程。 相反,上面的preexec_fn 會覆蓋信號的默認處理程序,從而忽略信號。 因此,如果子進程再次覆蓋SIGINT處理程序,則此解決方案可能不起作用。
另一個注意事項:此解決方案適用於各種子進程,即它不僅限於用 Python 編寫的子進程。 例如,我正在為其編寫包裝器的專用服務器實際上是用 Java 編寫的。
結合其他一些可以解決問題的答案 - 發送到主應用程序的信號不會被轉發到子進程。
import os
from subprocess import Popen
def preexec(): # Don't forward signals.
os.setpgrp()
Popen('whatever', preexec_fn = preexec)
你可以做這樣的事情,使其在 windows 和 unix 中工作:
import subprocess
import sys
def pre_exec():
# To ignore CTRL+C signal in the new process
signal.signal(signal.SIGINT, signal.SIG_IGN)
if sys.platform.startswith('win'):
#https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
#CREATE_NEW_PROCESS_GROUP=0x00000200 -> If this flag is specified, CTRL+C signals will be disabled
my_sub_process=subprocess.Popen(["executable"], creationflags=0x00000200)
else:
my_sub_process=subprocess.Popen(["executable"], preexec_fn = pre_exec)
經過一個小時的各種嘗試,這對我有用:
process = subprocess.Popen(["someprocess"], creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP)
這是windows的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.