在 Python 中禁用 DSUSP
Disable DSUSP in Python
一个 OSX 用户 submitted a bug that CTRL+Y causes a python terminal application to be suspended, via dsusp causing SIGTSTP to be sent when the Python program tried to read on stdin. The code below to solves the problem: (context)
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 的程序似乎忽略了 CTRL+Y on OSX,所以它至少相当普遍。我很久以前就在我的 .bashrc 中添加了
stty dsusp undef
,所以没有注意到它。
要查看此挂起行为,运行 cat
并输入 CTRL+Y Return OSX 或其他具有此功能的东西。
$ cat
^Y
[1]+ Stopped cat
$ fg
cat
cat: stdin: Resource temporarily unavailable
我无法检查此行为的实际行为,因为我没有任何计算机的操作系统会出现 DSUSP
行为。
然而,在调查这个问题时,我遇到了 issue 7695 in Python bug tracker。 VDSUSP
似乎只在 3.4 之后的 termios
中可用。
Glibc documentation,也就是说
Macro: int VDSUSP
This is the subscript for the DSUSP
character in the special control character array. termios.c_cc[VDSUSP]
holds the character itself.
The DSUSP
(suspend) character is recognized only if the implementation supports job control (see Job Control). It sends a SIGTSTP
signal, like the SUSP
character, but not right away—only when the program tries to read it as input. Not all systems with job control support DSUSP; only BSD-compatible systems (including GNU/Hurd systems).
因此,我建议您检查 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 标准。
一个 OSX 用户 submitted a bug that CTRL+Y causes a python terminal application to be suspended, via dsusp causing SIGTSTP to be sent when the Python program tried to read on stdin. The code below to solves the problem: (context)
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 的程序似乎忽略了 CTRL+Y on OSX,所以它至少相当普遍。我很久以前就在我的 .bashrc 中添加了
stty dsusp undef
,所以没有注意到它。
要查看此挂起行为,运行 cat
并输入 CTRL+Y Return OSX 或其他具有此功能的东西。
$ cat
^Y
[1]+ Stopped cat
$ fg
cat
cat: stdin: Resource temporarily unavailable
我无法检查此行为的实际行为,因为我没有任何计算机的操作系统会出现 DSUSP
行为。
然而,在调查这个问题时,我遇到了 issue 7695 in Python bug tracker。 VDSUSP
似乎只在 3.4 之后的 termios
中可用。
Glibc documentation,也就是说
Macro: int
VDSUSP
This is the subscript for the
DSUSP
character in the special control character array.termios.c_cc[VDSUSP]
holds the character itself.The
DSUSP
(suspend) character is recognized only if the implementation supports job control (see Job Control). It sends aSIGTSTP
signal, like theSUSP
character, but not right away—only when the program tries to read it as input. Not all systems with job control support DSUSP; only BSD-compatible systems (including GNU/Hurd systems).
因此,我建议您检查 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 标准。