一个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标准。