在一个Celery 任务中,我启动了一个subprocess,需要(1)能够发送一个SIGINT,同时(2)还可以访问子进程的stdout和stderr.我可以做其中的一个,但不能同时做两个.

当子进程中的命令以列表或带有bash前缀的字符串形式给出时,我可以发送SIGINT:

proc = subprocess.Popen(,
    [sys.executable, "-m", path.to.module, myarg1, myarg2, ...],    # also works with f"/bin/bash -c {sys.executable} -m path.to.module {myarg1} {myarg2} ..."
    stdin=sys.stdin, stdout=PIPE, stderr=PIPE, shell=False
)

据我所知,这两种 Select 最终都会启动bash,似乎只有运行中的bash才会对SIGINT做出react .

相反,运行"python-m..."意味着我的程序不再对SIGINT做出react ,但另一方面,它允许我开始查看stdout/stderr并在我的python程序中记录:

proc = subprocess.Popen(,
    f"{sys.executable} -m path.to.module {myarg1} {myarg2} ..."
    stdin=sys.stdin, stdout=PIPE, stderr=PIPE, shell=False
)

有了上面的内容,现在我不能再向我的程序发送SIGINT,但日志(log)记录工作正常.

我怎样才能让这两件事同时工作呢?我try 过shell=True次和各种stdin/out/err调整,但没有运气.

编辑:使用最上面的表单(命令作为列表),并在path.to.module中的程序中添加signal.signal(),我既可以接收SIGINT,也可以看到一些输出.

推荐答案

需要能够发送一个SIGINT.

我不同意这个前提.

我认为在某些情况下需要"停止正在运行的进程" 合理的方式,INT、USR1、HUP或其他信号可能就足够了. 关键是要让相关信号的信号处理程序处于活动状态.

另一个细节是"访问...stdout",它是 完全合情合理.就是我们不想要一百 终止,但我们希望将printf(3)缓冲区 在终止前由WRITE(2)系统调用刷新.

所以关键是我们需要子进程(或者可能是进程组) 以向其发送它期望的信号,然后处理 发出漂亮的信号.


bash会捕获某些信号,因此这绝对是一个令人担忧的问题.

proc = subprocess.Popen(
    ... , shell=False)

...这两种 Select 最终都会启动bash

不,至少在这种情况下不是. False的论点意味着bash在这里不涉及.


考虑一下def%的handler%,然后

signal.signal(signal.SIGUSR1, handler)

操作者可以 Select 呼叫sys.exit, 以便刷新标准输出缓冲区.

https://docs.python.org/3/library/signal.html#signal.signal

Python相关问答推荐

Python plt.text中重叠,包adjust_text不起作用,如何修复?

如何通过多2多字段过滤查询集

仅从风格中获取 colored颜色 循环

大Pandas 胚胎中产生组合

@Property方法上的inspect.getmembers出现意外行为,引发异常

由于NEP 50,向uint 8添加-256的代码是否会在numpy 2中失败?

当从Docker的--env-file参数读取Python中的环境变量时,每个\n都会添加一个\'.如何没有额外的?

pyscript中的压痕问题

基于索引值的Pandas DataFrame条件填充

Pandas DataFrame中行之间的差异

Pandas Loc Select 到NaN和值列表

python中的解释会在后台调用函数吗?

为什么if2/if3会提供两种不同的输出?

numpy.unique如何消除重复列?

如何防止Pandas将索引标为周期?

具有相同图例 colored颜色 和标签的堆叠子图

基于Scipy插值法的三次样条系数

有没有办法让Re.Sub报告它所做的每一次替换?

分解polars DataFrame列而不重复其他列值

如果服务器设置为不侦听创建,则QWebSocket客户端不连接到QWebSocketServer;如果服务器稍后开始侦听,则不连接