我发现以下情况经常发生在我身上:
- 我在交互式终端会话中使用 Python
- 我不小心输入了一些括号不匹配的内容
- Python 给我一个
...
提示,希望我输入另一行代码 - 为了回到 Python 命令提示符,我本能地输入
ctrl-D
(传输结束字符) - Python 进程没有返回到
>>>
提示符,而是立即退出,丢失了我交互会话中的所有数据
我希望这种情况不再发生。因此我的问题是:
有没有办法可以防止
ctrl-D
按下 时 Python 退出?这可能只是一厢情愿,但是有什么方法可以让
ctrl-D
我回到我一直期望的 Python 提示符?
我在 Mac 上使用 MacPorts 安装的 Python 3.6,但我想这是一个与平台无关的问题。我相信此安装使用 Gnu Readline 库进行用户交互,以防万一。
答案1
在使用“cooked”模式的基本程序中,例如cat
,Ctrl+D在tty层上挂接为结束语字符 - 它不会直接发送给进程,而是生成“EOF”条件,导致进程突然从其调用中收到 0 字节结果read(stdin)
。(进程可以只记录该条件并继续。)
理论上,由于 Python 使用 Readline,因此它不受此影响;它以“cbreak”模式使用终端,并让 Readline 处理所有特殊字符,包括 Ctrl+D。(也就是说,按下该键只会从 read 返回“\x04”,然后由 Readline 绑定在内部处理。)
然而,Readline 会自动绑定它在 tty 层上看到的已绑定的控制字符,并且没有选项可以从 Python 内部控制它。(尽管它有一个 ~/.inputrc 选项,但它似乎在 Python 中被忽略了。)
有没有办法可以防止按下 ctrl-D 时 Python 退出?;
因此似乎没有办法阻止 Python 的 readline 将 Ctrl+D 处理为 EOF除非tty 层有结束语绑定到其他内容(但并非完全解除绑定)。您唯一的选择是在 tty 层临时将 EOF 字符重新定义为除 Ctrl+D 之外的其他内容(使用stty eof
),并在退出时将其重新定义为正确的值。
尝试将其放入您的 $PYTHONSTARTUP 文件中:
if True:
import atexit, os
os.system("stty eof ^X")
atexit.register(lambda: os.system("stty eof ^D"))
(请注意,完全取消定义eof
在这里不起作用 - 如果 Readline 发现空,它将默认采用 Ctrl+D。)
除上述情况外,如果我确实输入了不匹配的括号,退出提示
...
并返回到>>>
不运行我输入的代码的正确方法是什么?
按Ctrl+C。Python 和大多数 shell 一样,接受 SIGINT 来执行此操作。