4

我正在使用 subprocess.Popen 运行多个进程,当我检测到一组文件中的任何一个发生更改时,我想向其中一个进程发送信号。我在进程中定义了一个信号处理程序,但似乎没有发送任何信号。一些帮助将不胜感激。发送信号的函数和信号处理程序如下所示。

def start_up():
    p, i = None, None
    while 1:
        subprocess.call(['clear'])
        logging.info('starting overlay on host %s' % socket.gethostname())
        p = subprocess.Popen([sys.executable, 'sdp_proc.py'])
        i = subprocess.Popen([sys.executable, 'kernel.py', sys.argv[1],
                                 sys.argv[2]])
        if file_modified():
            p.terminate()
            i.send_signal(signal.SIGINT)
        time.sleep(1)

信号处理程序如下所示:

def signal_handler(signum, frame):
    with open('log.txt', 'w') as f:
        f.write(' so what mate, received signal with signal number %s' % signum)


signal.signal(signal.SIGINT, signal_handler)
4

2 回答 2

2

我猜想 SIGINT 甚至在它有机会加载所有 Python 之前就被发送到子进程,所以在它安装 SIGINT 处理程序之前,这意味着它会立即死亡。

在向子进程发送您希望由您自己的处理程序代码处理的任何 SIGINT 信号之前,您可能希望观察子进程是否满足某些成功加载条件(可能只是在管道上发送一个字节)。

于 2013-07-24T19:21:49.197 回答
0

根据 和 中的官方文档,如果使用Unix,则NT需要使用进程组来接收信号shell=True

所以,我决定包装内置Popen函数来实现这种行为。

import subprocess as sp
import os

def Popen(command, env=None, **kw):
    if os.name == 'nt':
        # On Windows, the specified env must include a valid SystemRoot
        # Use a current value
        if env is None:
            env = {}

        env['SystemRoot'] = os.environ['SystemRoot']
        kw['creationflags'] = sp.CREATE_NEW_PROCESS_GROUP
    else:
        kw['preexec_fn'] = os.setpgrp

    return sp.Popen(command, env=env, **kw)

跨平台杀功能:

if os.name == 'nt':
    # On Windows, os module can't kill processes by group
    # Kill all children indiscriminately instead
    def killpg_by_pid(pid, s):
        # Ignoring s due the lack of support in windows.j
        sp.call(['taskkill', '/T', '/F', '/PID', str(pid)])

else:

    def killpg_by_pid(pid, s):
        os.killpg(os.getpgid(pid), s)

用法:

在 Linux 和 Windows 中测试。

import signal

process = Popen(
    command,
    stdout=sp.PIPE,
    stderr=sp.PIPE,
    shell=True,
    **kw,
)

# Kill
killpg_by_pid(process.pid, signal.SIGTERM)

有关完整示例,请查看:bddcli

于 2021-09-23T10:15:36.347 回答