python 如何使用stdin参数将ctrl-c传递到子进程popen

sd2nnvve  于 2023-02-18  发布在  Python
关注(0)|答案(2)|浏览(369)

我习惯于在我的python脚本中逐个子进程.Popen启动命令。大多数脚本如下:Popen(shlex(cmd), stdin=PIPE, stdout=PIPE, sterr=STDOUT)
现在我有一个命令接收到“CTRL-C”进入“命令行界面”模式以接受调试指令的情况。似乎Popen不支持像stdin=input那样将标准输入传递给参数stdin。我知道我可以使用使用标准输入/输出作为其输入/输出的os.system(cmd),但这不是我的解决方案。
好让人给我看另一个解决方案?先谢了。

o7jaxewo

o7jaxewo1#

你可能想发送中断信号。使用os.killkill -SIG $SUBPROCESS_PID作为子进程的进程ID。这与使用Ctrl+C相同,只是直接向子进程发送信号。
为此,您需要知道所产生的子进程的PID。

import signal,shlex
from subprocess import Popen
cmd = 'top'
sub_proc = Popen(shlex(cmd), stdin=PIPE, stdout=PIPE, sterr=STDOUT)
with open("./pid",'w') as f:
    f.write(sub_proc.pid)

此外,您还需要处理要打印调试信息的命令中的信号

def signal_handler(sig, frame):
    print('Received SIGINT  (Ctrl+C) ')

signal.signal(signal.SIGINT, signal_handler)
print('Awaiting Signal')
signal.pause()

拿到PID后,你就可以
cat ./pid | kill -SIGINT添加到进程,或者从python:

import os

with open("./pid",'r') as f:
   pid = int(f.read())

os.kill(pid, signal.SIGINT)
rdlzhqv9

rdlzhqv92#

ctrl+c是一个signal,信号不会传递到标准输入(默认情况下),而是发送到连接到终端的所有进程,每个进程负责处理它(因此父进程和子进程都必须处理KeyboardInterrupt异常或注册signal handler),从父进程向子进程转发stdin不会改变这一点。
如果您仍然希望转发stdin(它只转发写入控制台的文本),那么您可以传递stdin=sys.stdin而不是PIPE

**编辑:**要在ctrl+c下进入调试模式,父级必须注册一个信号处理程序以跳过SIGINT,子级必须注册另一个信号处理程序到pause on ctrl+c,并且子级应该有stdin=sys.stdin, stdout=sys.stdout以打印和从控制台读取。

相关问题