How to terminate a python subprocess launched with shell=True

前端 未结 12 2705
轮回少年
轮回少年 2020-11-21 04:53

I\'m launching a subprocess with the following command:

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

However, when I try t

相关标签:
12条回答
  • 2020-11-21 05:03

    I have not seen this mentioned here, so I am putting it out there in case someone needs it. If all you want to do is to make sure that your subprocess terminates successfully, you could put it in a context manager. For example, I wanted my standard printer to print an out image and using the context manager ensured that the subprocess terminated.

    import subprocess
    
    with open(filename,'rb') as f:
        img=f.read()
    with subprocess.Popen("/usr/bin/lpr", stdin=subprocess.PIPE) as lpr:
        lpr.stdin.write(img)
    print('Printed image...')
    

    I believe this method is also cross-platform.

    0 讨论(0)
  • 2020-11-21 05:04

    If you can use psutil, then this works perfectly:

    import subprocess
    
    import psutil
    
    
    def kill(proc_pid):
        process = psutil.Process(proc_pid)
        for proc in process.children(recursive=True):
            proc.kill()
        process.kill()
    
    
    proc = subprocess.Popen(["infinite_app", "param"], shell=True)
    try:
        proc.wait(timeout=3)
    except subprocess.TimeoutExpired:
        kill(proc.pid)
    
    0 讨论(0)
  • 2020-11-21 05:04

    I could do it using

    from subprocess import Popen
    
    process = Popen(command, shell=True)
    Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid))
    

    it killed the cmd.exe and the program that i gave the command for.

    (On Windows)

    0 讨论(0)
  • 2020-11-21 05:07

    what i feel like we could use:

    import os
    import signal
    import subprocess
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
    
    os.killpg(os.getpgid(pro.pid), signal.SIGINT)
    

    this will not kill all your task but the process with the p.pid

    0 讨论(0)
  • 2020-11-21 05:11

    When shell=True the shell is the child process, and the commands are its children. So any SIGTERM or SIGKILL will kill the shell but not its child processes, and I don't remember a good way to do it. The best way I can think of is to use shell=False, otherwise when you kill the parent shell process, it will leave a defunct shell process.

    0 讨论(0)
  • 2020-11-21 05:12

    Use a process group so as to enable sending a signal to all the process in the groups. For that, you should attach a session id to the parent process of the spawned/child processes, which is a shell in your case. This will make it the group leader of the processes. So now, when a signal is sent to the process group leader, it's transmitted to all of the child processes of this group.

    Here's the code:

    import os
    import signal
    import subprocess
    
    # The os.setsid() is passed in the argument preexec_fn so
    # it's run after the fork() and before  exec() to run the shell.
    pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
                           shell=True, preexec_fn=os.setsid) 
    
    os.killpg(os.getpgid(pro.pid), signal.SIGTERM)  # Send the signal to all the process groups
    
    0 讨论(0)
提交回复
热议问题