【问题标题】:python subprocesses (of process with subprocesses) on termination hang in OSX activity monitor终止时的python子进程(具有子进程的进程)挂在OSX活动监视器中
【发布时间】:2013-06-21 22:50:51
【问题描述】:

我正在为我编写的 udp 服务器编写测试工具。这个想法是使用 multiprocessing.pool 为服务器的多个实例执行 subprocess.call 命令 (per this question)。 udp 服务器是另一个 python 程序,它由 3 个进程(主进程、http 接口和 udp 服务器)组成。在我尝试编写测试脚本时,当我使用 CTRL+C 终止测试脚本时,我的活动监视器中总是会出现 2-5 个挂起的 python2.7 进程。

我的尝试:

  1. 普通子进程
  2. 处理 bash 的子进程未连接到终端 (see this question)
  3. multiprocess.pool,还使用简单的 test.py 脚本创建挂起进程(见下文)

我尝试在服务器代码中添加子进程终止,但无济于事。当我在终端内运行服务器时,它会正确响应 CTRL+C。我认为这与服务器内部的子进程有关,因为 (1) 和 (2) 的 test.py 脚本没有问题。


1) 只使用子进程:

args0 = [sys.executable, server_path, '-p', '7000', '-t', '8000', '-u', '9000']
args1 = [sys.executable, server_path, '-p', '7001', '-t', '8001', '-u', '9001']

p0 = subprocess.Popen(args0)
p1 = subprocess.Popen(args1)

2) 使用带有 stdout、管道、os.kill 的子进程:

p0 = subprocess.Popen(  args0, 
                        stdout=subprocess.PIPE, 
                        stderr=subprocess.STDOUT, 
                        close_fds=True)
print "running for 5s..."
time.sleep(5)
os.kill(p0.pid, signal.SIGTERM)

3a) test_harness.py(带池)

import sys, os, time
import subprocess, multiprocessing

def work(cmd):
    return subprocess.call(cmd) # , shell=False

def main():
    server_path = os.getcwd() + '/' + 'test.py'

    args0 = [sys.executable, server_path, '-p', '7000']
    # args1 = [sys.executable, server_path, '-p', '7001']
    tasks = [args0]

    pool = multiprocessing.Pool(processes=1)
    pool.map_async(work, tasks)
    time.sleep(3)
    pool.terminate()

if __name__ == '__main__':
    main()

3b) 测试.py

def main():
    while True:
        a = 1

if __name__ == '__main__':
    main()

【问题讨论】:

  • 好吧,如果os.kill(p0.pid, signal.SIGTERM) 没有杀死子进程,听起来你的子进程忽略了SIGTERM

标签: python macos subprocess multiprocessing


【解决方案1】:

终于搞定了。此代码生成两个多线程服务器实例,作为测试工具中的子进程。您从子进程获得所有控制台输出,并且当您从终端 CTRL+C 测试工具时,所有子进程也会死掉。 subprocess.Popen 最终对我不起作用。

def runInstance(args):
    # NOTE: We don't do the stdout or stderr args
    p = subprocess.call(args, 
                        # stdout=subprocess.PIPE, 
                        # stderr=subprocess.STDOUT, 
                        close_fds=True, 
                        shell=True
                        )

def main():
    print "Starting test harness..."
    server_path = os.getcwd() + '/' + 'server.py'
    args0 = [sys.executable, server_path, '-p', '7000', '-t', '8000', '-u', '9000']
    args1 = [sys.executable, server_path, '-p', '7001', '-t', '8001', '-u', '9001']

    # Start server instances
    # NOTE: It is target=runInstance, not target=runInstance()
    p0 = multiprocessing.Process(target=runInstance, args=(' '.join(args0),))
    p1 = multiprocessing.Process(target=runInstance, args=(' '.join(args1),))
    p0.start()
    p1.start()

【讨论】:

    猜你喜欢
    • 2011-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-11
    相关资源
    最近更新 更多