我正在尝试在python中按键调用函数。当脚本在 Windows 命令行 (cmd.exe( 中运行时,一切都按预期工作。但通常当我在Windows上时,我会使用薄荷。
在薄荷中,应用程序的行为不同。getch()
会阻止应用程序(永久(。
import msvcrt
print("press a key")
char = msvcrt.getch()
print(f"you pressed: {char}")
在 Windows 命令行中:
按一个键
(按a键(
你按:B'A'
(应用程序已关闭(
薄荷:
按一个键
(多次按(
啊
(什么也没发生(
简短的回答是"确保Windows python可执行调用包含在winpty
调用中"。
我有一个类似的挑战,我希望支持一个完全交互式的控制台应用程序,该应用程序在Unixey环境中使用termios
,在Windows中使用msvcrt
。
- 它适用于Linux和Mac,
- 它适用于Windows CMD控制台,
- 它适用于时髦的Windows bash终端,如VS Code终端,
- 它可以在"纯"MSy2中工作(其中Python通过pacman安装,编译为在
mintty
中运行,因此支持termios
(,但是 - 它在"Git for Windows"的薄荷bash窗口中失败,除非调用者在命令之前添加"winpty"...当它失败时,它就会失败!(无法轻松摆脱损坏的控制台应用程序,因为读取键不起作用(
我在这里看到的最大挑战是检测该故障。
到目前为止,我有以下条件:
- 如果加载了
msvcrt
(我们在Windows python中运行( - 和
os.environ.get('TERM_PROGRAM') == "mintty"
(薄荷是控制台( - 和
os.environ.get('TERM') == "xterm"
(winpty没有从mintty的xterm默认值更改终端类型( - 然后引发异常,要求用户使用
winpty
进行调用
这依赖于我的系统上的一系列奇怪的巧合:
- mintty的默认"TERM"设置是"xterm"(但可配置!
- 与最近的 Git 捆绑在一起的 Winpty 将其重置为
None
(用 Python 术语( - 与MSis2捆绑在一起的Winpty将其重置为"XTERM-256Color">
不幸的是,我不认为这个逻辑是很可靠的 - 其他版本的 winpty 和 mintty 的行为可能不同,用户可能已将 mintty 中的终端类型设置更改为"xterm"以外的内容,在这种情况下,我的脚本将错误地假设一切正常。
我非常喜欢一种更可靠的方法来检测我的脚本何时在"python for windows 运行在 mintty 中,没有 winpty"。
更新:使用Bash可以工作!
对于它的价值,如果你可以依靠路径中可用的bash(如果你试图从python中检测mintty,实际上我猜很可能?(,那么你可以:
- 调用 bash 脚本(不管道 stdin 和 stdout,并传递参数
-i
,因此它连接到终端,并与( - 依靠Mintty的辅助设备属性支持
- 使用
echo -n -e
打印转义序列 - 使用超时
read
捕获 tty 响应 - 使用 stderr 或退出代码将结果输出到 python
示例 bash 脚本:
echo -n -e 'e[>c';
read -rs -t 0.2 -d "" <$(tty)
echo "Look ma! Secondary device attributes are ${REPLY#?} - now if they start with [>77; then I know I'm in mintty."