Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python:杀死儿童或报告他们成功的简单方法?_Python_Subprocess_Parent Child_Multiprocessing - Fatal编程技术网

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

python:杀死儿童或报告他们成功的简单方法?,python,subprocess,parent-child,multiprocessing,Python,Subprocess,Parent Child,Multiprocessing,我想 并行调用shell命令(例如下面的“sleep”) 报告各自的开始和完成情况,以及 能够用“kill-9父进程”杀死它们 已经有很多关于这类东西的文章,但我觉得我还没有找到我正在寻找的优雅的pythonic解决方案。对于完全不熟悉python的人来说,我还试图保持相对可读性(且简短) 到目前为止,我的方法(见下面的代码)是: 将subprocess.call(unix_命令)放入一个包装函数中,该函数报告命令的开始和完成 使用multiprocess.Process调用包装函数 跟踪适当的

我想

  • 并行调用shell命令(例如下面的“sleep”)
  • 报告各自的开始和完成情况,以及
  • 能够用“kill-9父进程”杀死它们
  • 已经有很多关于这类东西的文章,但我觉得我还没有找到我正在寻找的优雅的pythonic解决方案。对于完全不熟悉python的人来说,我还试图保持相对可读性(且简短)

    到目前为止,我的方法(见下面的代码)是:

  • 将subprocess.call(unix_命令)放入一个包装函数中,该函数报告命令的开始和完成
  • 使用multiprocess.Process调用包装函数
  • 跟踪适当的PID,全局存储它们,并在信号处理器中杀死它们
  • 我试图避免周期性轮询进程的解决方案,但我不知道为什么

    有更好的方法吗

    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)
    
    一旦返回,子进程就完成了,
    call
    的返回值就是子进程的
    returncode
    。因此,在列表
    pids
    中累积这些返回码(顺便说一句,附加它的多进程和“主”进程之间不同步)并发送它们
    9
    信号“好像”它们是进程ID而不是返回码,这绝对是错误的

    问题的另一个明显错误是规格:

    可以用'kill-9'杀死他们 父级\u进程\u pid'

    由于
    -9
    意味着父进程不可能截获信号(这是明确指定
    -9
    的目的)——因此我认为
    -9
    在这里是虚假的

    您应该使用
    线程
    而不是
    多处理
    (每个“保姆”线程或进程基本上什么都不做,只是等待其子进程,那么为什么要在这样一个轻量级任务上浪费进程?-);您还应该在主线程中调用
    supprocess.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)
    
    这段代码(下面的代码)似乎适合我,从“top”或命令行的ctrl-c进行杀戮。与Alex的建议相比,唯一真正的变化是将subprocess.Process替换为subprocess.Popen调用(我认为subprocess.Process不存在)

    这里的代码也可以通过某种方式锁定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)
    

    +我不知道巨蟒能杀死儿童…@Zonda333:哦,当然<代码>来自未来导入谋杀。谢谢,这很有帮助。我会在清理完后发回的@马蒂克,不客气!我编辑了我的A,以大致说明我将如何看到最好的代码结构。这对我来说是一个很好的教训。我想我是在第一次接触linux设备时养成了“-9”的习惯。我在一个单独的答案中包含了上面代码的一个稍加修改的版本。@Alex:为什么
    sigterm\u handler
    必须显式地杀死所有守护进程线程,而
    sigint\u handler
    却没有?尽管
    t.daemon=True
    ,显式的
    p.kill
    s似乎确实是需要的。我还感到困惑的是,即使注释掉了
    t.daemon=True
    ,程序的行为(在SIGTERM或SIGINT之后)似乎也没有改变。
    t.daemon=True
    的目的是什么?您是对的,没有子进程.Process--很抱歉thinko;-,现在编辑我的A以修复它。