How to terminate a python subprocess launched with shell=True

前端 未结 12 2708
轮回少年
轮回少年 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:14

    Although it is an old question, it has a high google rank. so I decided to post an answer with the new method someone can use in python 3 to manage this easily and with confidence. as of python 3.5 you there is a new method added to subprocess package called run().

    As the documentation says:

    It is the recommended approach to invoking sub processes for all use cases it can handle. For more advanced use cases, the underlying Popen interface can be used directly.

    The subprocess.run():

    Runs a command described by args. Wait for the command to complete, then return a CompletedProcess instance.

    for example one can run this snippet within a python console:

    >>> subprocess.run(["ls", "-l"])  # doesn't capture output
    CompletedProcess(args=['ls', '-l'], returncode=0)
    

    P.S. In case of the OP's specific question, I wasn't able to reproduce his problem. commands I run with popen() are terminating properly.

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

    None of this answers worked for me so Im leaving the code that did work. In my case even after killing the process with .kill() and getting a .poll() return code the process didn't terminate.

    Following the subprocess.Popen documentation:

    "...in order to cleanup properly a well-behaved application should kill the child process and finish communication..."

    proc = subprocess.Popen(...)
    try:
        outs, errs = proc.communicate(timeout=15)
    except TimeoutExpired:
        proc.kill()
        outs, errs = proc.communicate()
    

    In my case I was missing the proc.communicate() after calling proc.kill(). This cleans the process stdin, stdout ... and does terminate the process.

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

    Send the signal to all the processes in group

        self.proc = Popen(commands, 
                stdout=PIPE, 
                stderr=STDOUT, 
                universal_newlines=True, 
                preexec_fn=os.setsid)
    
        os.killpg(os.getpgid(self.proc.pid), signal.SIGHUP)
        os.killpg(os.getpgid(self.proc.pid), signal.SIGTERM)
    
    0 讨论(0)
  • 2020-11-21 05:21

    As Sai said, the shell is the child, so signals are intercepted by it -- best way I've found is to use shell=False and use shlex to split the command line:

    if isinstance(command, unicode):
        cmd = command.encode('utf8')
    args = shlex.split(cmd)
    
    p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    

    Then p.kill() and p.terminate() should work how you expect.

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

    I know this is an old question but this may help someone looking for a different method. This is what I use on windows to kill processes that I've called.

    si = subprocess.STARTUPINFO()
    si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    subprocess.call(["taskkill", "/IM", "robocopy.exe", "/T", "/F"], startupinfo=si)
    

    /IM is the image name, you can also do /PID if you want. /T kills the process as well as the child processes. /F force terminates it. si, as I have it set, is how you do this without showing a CMD window. This code is used in python 3.

    0 讨论(0)
  • 2020-11-21 05:27
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
    p.kill()
    

    p.kill() ends up killing the shell process and cmd is still running.

    I found a convenient fix this by:

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

    This will cause cmd to inherit the shell process, instead of having the shell launch a child process, which does not get killed. p.pid will be the id of your cmd process then.

    p.kill() should work.

    I don't know what effect this will have on your pipe though.

    0 讨论(0)
提交回复
热议问题