在 Python 中禁用 DSUSP



一个OSX用户提交了一个错误,即CTRL + Y导致python终端应用程序被挂起,通过dsusp导致当Python程序尝试读取stdin时发送SIGTSTP。下面的代码来解决问题:(上下文)

import sys
import termios
if sys.platform == 'darwin':
    attrs = termios.tcgetattr(0)
    VDSUSP = termios.VSUSP + 1
    attrs[-1][VDSUSP] = 0
    termios.tcsetattr(0, termios.TCSANOW, attrs)
  • 如何检测此功能 (dsusp)?是否有我可以基于os.uname()或类似方法使用的启发式方法?
  • termios.VDSUSP不存在,即使在拥有它的系统上也是如此。它丢失的原因是什么?
  • 这种关闭它的行为有多普遍?使用readline的程序似乎忽略了OSX上的CTRL + Y,因此它至少是相当普遍的。我很久以前就在我的 .bashrc 中添加了stty dsusp undef,所以没有注意到它。

若要查看此挂起行为,请运行cat并在 OSX 上输入 CTRL+YReturn 或使用此功能的其他内容。

$ cat
^Y
[1]+ Stopped             cat
$ fg
cat
cat: stdin: Resource temporarily unavailable

我无法检查此的实际行为,因为我没有任何计算机的操作系统具有DSUSP行为。但是,在调查该问题时,我在Python错误跟踪器中遇到了问题7695。似乎VDSUSP仅在 3.4 开始在 termios 中可用。


Glibc 文档,上面写着

宏:整数VDSUSP

这是特殊控制字符数组中DSUSP字符的下标。 termios.c_cc[VDSUSP]包含角色本身。

仅当实现支持作业控制时,才能识别DSUSP(挂起)字符(请参阅作业控制)。它发送一个SIGTSTP信号,如SUSP字符,但不是立即 - 只有当程序尝试将其读取为输入时。并非所有具有作业控制的系统都支持 DSUSP;只有与BSD兼容的系统(包括GNU/Hurd系统)。


因此,我建议你检查termios中是否存在VDSUSP - 它将从 3.4 开始存在;否则回退到

if any(i in sys.platform for i in ['bsd', 'darwin']):

哪个应该匹配BSD和你的OS X;Hurd是一个很大的问号,因为我无法找出你的修复是否正确(我想它会在所有BSD版本上类似地工作)。

更容易的是只做:

import subprocess
import time
from distutils.spawn import find_executable
def exec_cmd(*args):
    p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, _ = p.communicate()
    return stdout
if find_executable('stty'):
    modesave = exec_cmd('stty', '-g').strip()
    exec_cmd('stty', 'dsusp', 'undef')
    print("disabled ctrl-y")
    time.sleep(2)
    print("enabled ctrl-y")
    exec_cmd('stty', modesave)
    time.sleep(2)
    print("exiting")

至少这不会炸毁我的Linux,stty命令本身和-g等都是POSIX标准。

相关内容

  • 没有找到相关文章

最新更新