如何终止脚本通过命令行启动的进程?Python杀线程失效问题求解
问题原因
os.system()、subprocess.run()都属于阻塞式的系统调用,执行过程中当前Python线程会把控制权交给操作系统,挂起等待外部进程执行结束才会回到Python的执行上下文。- 你用到的
PyThreadState_SetAsyncExc原理是给目标Python线程标记一个待抛出的异常,这个异常只会在目标线程下一次执行Python字节码的时候才会触发。线程阻塞在系统调用阶段时根本不会执行Python字节码,所以异常只能等外部进程运行结束、system调用返回后才会生效,自然无法实现提前终止。 - 另外你的需求本质是终止外部独立的客户端进程,就算能杀死Python工作线程,已经启动的外部子进程会变成孤儿进程继续运行,本来就解决不了问题。
可行解决方案
不要用Python线程封装客户端启动逻辑,直接用subprocess.Popen非阻塞启动客户端进程,保存进程对象,需要终止时直接调用进程的终止方法即可:
import subprocess import time if __name__ == "__main__": # 启动客户端进程,shell=True适配你传入的命令行字符串 client_proc = subprocess.Popen(ttest_s, shell=True) # 这里运行你的服务端逻辑,等到拿到需要的数据后 time.sleep(1) # 终止客户端进程 client_proc.terminate() # 等待进程退出回收系统资源 client_proc.wait() print("Terminating.")
如果需要同时启动多个客户端,把所有Popen对象存在列表里批量操作即可:
client_procs = [] # 批量启动所有客户端 for run_cmd in client_cmd_list: proc = subprocess.Popen(run_cmd, shell=True) client_procs.append(proc) # 需要终止时批量处理 for proc in client_procs: # 先判断进程是否还在运行 if proc.poll() is None: # 普通终止发SIGTERM,杀不掉可以换成proc.kill()发SIGKILL强制终止 proc.terminate() proc.wait()
如果需要异步监听客户端的输出,可以单独给每个子进程开线程读取stdout/stderr,终止时先杀进程,读线程读到EOF就会自动退出,不需要额外处理线程终止。
内容的提问来源于stack exchange,提问作者user123
相关产品推荐
相关产品推荐

