python:杀死孩子或报告他们成功的简单方法?

2024-05-02 02:13:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我想

  1. 并行调用shell命令(例如下面的“sleep”
  2. 报告各自的开始和完成情况,以及
  3. 可以用“kill-9 parent_process_pid”杀死它们。在

已经有很多关于这类事情的文章,但是我觉得我还没有找到我想要的优雅的Python解决方案。我还试图让那些完全不熟悉python的人相对可读(并且简短)。在

到目前为止,我的方法是:

  1. 把subprocess.call(unix_命令)在包装函数中,报告命令的开始和完成。在
  2. 使用调用包装器函数多进程. 在
  3. 跟踪适当的pid,将其全局存储,并在signal_处理程序中终止它们。在

我试图避免定期轮询进程的解决方案,但我不知道为什么。在

有更好的方法吗?在

import subprocess,multiprocessing,signal
import sys,os,time

def sigterm_handler(signal, frame):
        print 'You killed me!'
        for p in pids:
                os.kill(p,9)
        sys.exit(0)

def sigint_handler(signal, frame):
        print 'You pressed Ctrl+C!'
        sys.exit(0)

signal.signal(signal.SIGINT, sigint_handler)
signal.signal(signal.SIGTERM, sigterm_handler)

def f_wrapper(d):
        print str(d) + " start"
        p=subprocess.call(["sleep","100"])
        pids.append(p.pid)
        print str(d) + " done"

print "Starting to run things."

pids=[]

for i in range(5):
        p=multiprocessing.Process(target=f_wrapper,args=(i,))
        p.daemon=True
        p.start()

print "Got things running ..."

while pids:
        print "Still working ..."
        time.sleep(1)

Tags: 方法命令signaldef报告syssleep解决方案
2条回答

这段代码(下面的代码)似乎对我有用,从“top”或从命令行按ctrl-c。亚历克斯的建议唯一真正的改变是子流程。流程用一个子流程.Popen打电话(我不认为子流程。流程存在)。在

这里的代码也可以通过某种方式锁定stdout来改进,这样就没有机会在进程之间打印重叠。在

import subprocess, threading, signal
import sys, time

pobs = set()                            # set to hold the active-process objects
pobslock = threading.Lock()     # a Lock object to make sure only one at a time can modify pobs

def numpobs():
        with pobslock:
                return len(pobs)

# signal handlers
def sigterm_handler(signal, frame):
        print 'You killed me! I will take care of the children.'
        with pobslock:
                for p in pobs: p.kill()
        sys.exit(0)

def sigint_handler(signal, frame):
        print 'You pressed Ctrl+C! The children will be dealt with automatically.'
        sys.exit(0)

signal.signal(signal.SIGINT, sigint_handler)
signal.signal(signal.SIGTERM, sigterm_handler)


# a function to watch processes
def p_watch(d, p):
        print d, 'start', p.pid
        rc = p.wait()
        with pobslock:
                pobs.remove(p)
        print d, 'done, rc =', rc


# the main code
print "Starting to run things ..."
for i in range(5):
        p = subprocess.Popen(['sleep', '4'])
        with pobslock:
                pobs.add(p)
        # create and start a "daemon" to watch and report the process p.
        t = threading.Thread(target=p_watch, args=(i, p))
        t.daemon=True
        t.start()

print "Got things running ..."
while numpobs():
        print "Still working ..."
        time.sleep(1)

一旦^{}返回,子进程完成,call的返回值就是子进程的returncode。因此,将这些返回码累积到列表pids(在附加它的多进程和“main”进程之间不同步)并发送它们9信号“好像”它们是进程id而不是返回代码,这是绝对错误的。在

另一个绝对错误的问题是规格:

be able to kill them with 'kill -9 parent_process_pid'.

由于-9意味着父进程不可能截获信号(这是显式指定-9目的),因此我认为{}在这里是假的。在

您应该使用threading而不是multiprocessing(每个“保姆”线程或进程本质上只做等待其子进程的操作,那么为什么要在这样一个轻量级任务上浪费进程呢?-);您还应该在主线程中调用suprocess.Process(以启动子进程,并能够获得其.pid以放入列表中),并将生成的进程对象传递给等待它的babysitter线程(完成后报告并从列表中删除)。子进程id的列表应该由一个锁来保护,因为主线程和几个保姆线程都可以访问它,而且一个集合可能比一个列表(更快的删除)更好,因为您不关心排序或避免重复。在

所以,大致上(没有测试,所以可能会有bug;-)我会把你的代码改成s/东西,比如:

import subprocess, threading, signal
import sys, time

pobs = set()
pobslock = threading.Lock()
def numpobs():
    with pobslock:
        return len(pobs)

def sigterm_handler(signal, frame):
    print 'You killed me!'
    with pobslock:
        for p in pobs: p.kill()
    sys.exit(0)

def sigint_handler(signal, frame):
    print 'You pressed Ctrl+C!'
    sys.exit(0)

signal.signal(signal.SIGINT, sigint_handler)
signal.signal(signal.SIGTERM, sigterm_handler)

def f_wrapper(d, p):
    print d, 'start', p.pid
    rc = p.wait()
    with pobslock:
        pobs.remove(p)
    print d, 'done, rc =', rc

print "Starting to run things."

for i in range(5):
    p = subprocess.Popen(['sleep', '100'])
    with pobslock:
        pobs.add(p)
    t = threading.Thread(target=f_wrapper, args=(i, p))
    t.daemon=True
    t.start()

print "Got things running ..."

while numpobs():
    print "Still working ..."
    time.sleep(1)

相关问题 更多 >