如何阻止 SIGINT 被传递给 python 中的子进程?

发布于 2024-09-08 20:11:19 字数 141 浏览 2 评论 0原文

我的 python 脚本使用信号 process 模块拦截 SIGINT 信号以防止过早退出,但该信号被传递到我用 Popen 打开的子进程。是否有某种方法可以防止将此信号传递给子进程,以便当用户按 ctrl-c 时它也不会过早退出?

My python script intercepts the SIGINT signal with the signal process module to prevent premature exit, but this signal is passed to a subprocess that I open with Popen. is there some way to prevent passing this signal to the subprocess so that it also is not exited prematurely when the user presses ctrl-c?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

美煞众生 2024-09-15 20:11:19

当您启动子进程时,信号处理程序会被继承,因此如果您使用信号模块来忽略 SIGINT (signal.signal(signal.SIGINT, signal.SIG_IGN)),那么您的子进程也会自动忽略。

不过,有两个重要的警告:

  • 您必须在生成子进程之前设置忽略处理程序
  • 自定义信号处理程序将重置为默认处理程序,因为子进程获胜无法访问处理程序代码来运行它。

因此,如果您需要自定义对 SIGINT 的处理而不是仅仅忽略它,您可能希望在生成子进程时暂时忽略 SIGINT,然后(重新)设置自定义信号处理程序。

如果您尝试捕获 SIGINT 并设置一个标志,以便可以在安全点退出而不是立即退出,请记住,当您到达该安全点时,您的代码将必须手动清理其后代,因为您的子进程和任何它启动的进程将忽略 SIGINT。

Signal handlers are inherited when you start a subprocess, so if you use the signal module to ignore SIGINT (signal.signal(signal.SIGINT, signal.SIG_IGN)), then your child process automatically will also.

There are two important caveats, though:

  • You have to set the ignore handler before you spawn the child process
  • Custom signal handlers are reset to the default handlers, since the child process won't have access to the handler code to run it.

So if you need to customise your handling of SIGINT rather than just ignoring it, you probably want to temporarily ignore SIGINT while you spawn your child process, then (re)set your custom signal handler.

If you're trying to catch SIGINT and set a flag so you can exit at a safe point rather than immediately, remember that when you get to that safe point your code will have to manually clean up its descendants, since your child process and any processes it starts will be ignoring the SIGINT.

笑叹一世浮沉 2024-09-15 20:11:19

您可以使用 tty< 重新分配 ctrl-c 的角色/a> 模块,它允许您操纵信号的分配。但请注意,除非您将它们恢复到修改之前的状态,否则它们将在 shell 的整个会话中持续存在,即使在程序退出后也是如此。

下面是一个简单的代码片段,可帮助您开始存储旧的 tty 设置,将 ctrl-c 重新分配给 ctrl-x,然后在退出时恢复以前的 tty 设置。

import sys
import tty

# Back up previous tty settings
stdin_fileno = sys.stdin.fileno()
old_ttyattr = tty.tcgetattr(stdin_fileno)

try:
    print 'Reassigning ctrl-c to ctrl-x'

    # Enter raw mode on local tty
    tty.setraw(stdin_fileno)
    raw_ta = tty.tcgetattr(stdin_fileno)
    raw_ta[tty.LFLAG] |= tty.ISIG
    raw_ta[tty.OFLAG] |= tty.OPOST | tty.ONLCR

    # ^X is the new ^C, set this to 0 to disable it entirely
    raw_ta[tty.CC][tty.VINTR] = '\x18'  

    # Set raw tty as active tty
    tty.tcsetattr(stdin_fileno, tty.TCSANOW, raw_ta)

    # Dummy program loop
    import time
    for _ in range(5):
        print 'doing stuff'
        time.sleep(1)

finally:
    print 'Resetting ctrl-c'
    # Restore previous tty no matter what
    tty.tcsetattr(stdin_fileno, tty.TCSANOW, old_ttyattr)

You are able to re-assign the role of ctrl-c using the tty module, which allows you to manipulate the assignment of signals. Be warned, however, that unless you put them back the way they were before you modified them, they will persist for the shell's entire session, even after the program exits.

Here is a simple code snippet to get you started that stores your old tty settings, re-assigns ctrl-c to ctrl-x, and then restores your previous tty settings upon exit.

import sys
import tty

# Back up previous tty settings
stdin_fileno = sys.stdin.fileno()
old_ttyattr = tty.tcgetattr(stdin_fileno)

try:
    print 'Reassigning ctrl-c to ctrl-x'

    # Enter raw mode on local tty
    tty.setraw(stdin_fileno)
    raw_ta = tty.tcgetattr(stdin_fileno)
    raw_ta[tty.LFLAG] |= tty.ISIG
    raw_ta[tty.OFLAG] |= tty.OPOST | tty.ONLCR

    # ^X is the new ^C, set this to 0 to disable it entirely
    raw_ta[tty.CC][tty.VINTR] = '\x18'  

    # Set raw tty as active tty
    tty.tcsetattr(stdin_fileno, tty.TCSANOW, raw_ta)

    # Dummy program loop
    import time
    for _ in range(5):
        print 'doing stuff'
        time.sleep(1)

finally:
    print 'Resetting ctrl-c'
    # Restore previous tty no matter what
    tty.tcsetattr(stdin_fileno, tty.TCSANOW, old_ttyattr)
茶花眉 2024-09-15 20:11:19

对于 python 2 代码库:子进程已损坏。

正确的做法是

import subprocess32 as subprocess

参见 subprocess32

这是 Python 3 子进程模块的向后移植,用于 Python
2. 此代码尚未在 Windows 或其他非 POSIX 平台上进行测试。

For python 2 codebase: subprocess is broken.

The right thing is

import subprocess32 as subprocess

See subprocess32

This is a backport of the Python 3 subprocess module for use on Python
2. This code has not been tested on Windows or other non-POSIX platforms.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文