python 无法使用 process.terminate 终止进程

标签 python

我有一个Python代码如下:

import threading
import time
import subprocess, os, sys, psutil, signal
from signal import SIGKILL

def processing():
    global p_2
    global subp_2
    .
    .
    .
    if condition1: #loop again
          threading.Timer(10,processing).start()
    if condition2:
          signal.signal(signal.SIGINT, signal_handler)
          #signal.signal(signal.SIGTERM, signal_handler)
          subp_2.terminate()   
          #os.kill(subp_2.pid, 0)
          #subp_2.kill()            
          print " Status p_2: ", p_2.status

def signal_handler(signal, frame):
    print('Exiting')
    sys.exit(0)

def function():
    global p_1
    global subp_1
    .
    .
    .
    if condition1: #loop again
          threading.Timer(5,function).start()

    if condition2:

          signal.signal(signal.SIGINT, signal_handler)
          #signal.signal(signal.SIGTERM, signal_handler)
          subp_1.terminate()   
          #os.kill(subp_1.pid, 0)
          #subp_1.kill()            
          print " Status p_1: ", p_1.status
          threading.Timer(10,processing).start()  
          subp_2 =  subprocess.Popen('./myScript2.sh %s %s' % (arg0, arg1), shell=True)
          p_2 = psutil.Process(subp_2.pid)

if __name__ == '__main__':
          global p_1
          global subp_1 
          .
          .
          .
          subp_1 = subprocess.Popen(["/.../myScript1.sh"],  shell=True)
          p_1 = psutil.Process(subp_1.pid)
          threading.Timer(5,function).start()

我无法终止进程 subp_1 和 subp_2。无论我尝试什么:.terminate()、.kill() 或 os.kill() 我仍然得到进程状态正在运行。谁能告诉我我错过了什么?任何提示表示赞赏。

最佳答案

当您使用shell=True时,首先会生成一个运行shell的子进程。然后 shell 生成一个运行 myScript2.sh 的子进程。可以终止运行 shell 的子进程,而无需终止 myScript2.sh 子进程。

如果您可以避免使用shell=True,那么这将是避免此问题的一种方法。如果使用用户输入来形成命令,绝对应该避免 shell=True,因为它是 security risk .

在 Unix 上,默认情况下,由 subprocess.Popen 生成的子进程不是 session leader 。当您向 session 领导者发送信号时,该信号将传播到具有相同 session ID 的所有进程。因此,要让 shell 将 SIGTERM 传递给 myScript2.sh,请使 shell 成为 session 领导者。

对于 Unix 上的 Python 版本<3.2,可以通过运行 shell 进程os.setsid()来完成:

import os
subp_2 =  subprocess.Popen('./myScript2.sh %s %s' % (arg0, arg1), 
                           shell=True, 
                           preexec_fn=os.setsid)

# To send SIGTERM to the process group:
os.killpg(subp_2.pid, signal.SIGTERM)

对于 Unix 上的 Python 版本 >= 3.2,将 start_new_session=True 传递给 Popen

对于 Windows,请参阅 J.F. Sebastian's solution .

关于python 无法使用 process.terminate 终止进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23228650/

相关文章:

帕特里夏尝试的python实现

python - 使用 pandas web.DataReader 从整个索引(例如 DJIA)中获取数据

python - 作为 pip install 用户,我应该安装轮子吗?

java - Eclipse 不像为 Java 那样为 Python 提供快速修复选项

python - 对雪花中的所有存储过程授予执行权限

python - 如何在Python中将文本文件解析为字典,其中一行键后跟两行值

python - 如何将具有多个模块的 pygame 应用程序转换为 .exe

python - Numpy float 促销不一致

python - 如何根据给定的键列将多个字典组合到一个列表中?

python - 我可以访问已经可执行的 Python 脚本的代码吗?