【问题标题】:msvcrt.getch() detects space every timemsvcrt.getch() 每次都检测空间
【发布时间】:2018-04-27 20:04:19
【问题描述】:

我正在编写一个简单的 python 代码,它应该检测我的击键,但由于某种原因在每次击键后检测空间。

代码:

import msvcrt

print("press 'escape' to quit...")
text=""
while 1:
    char = msvcrt.getch()
    print(ord(char))

示例运行:

Input: aaaaa

Output:
97
0
97
0
97
0
97
0
97
0

【问题讨论】:

  • 那么问题出在哪里?你的代码打印是什么?

标签: python windows python-3.x msvcrt getch


【解决方案1】:

它没有检测到空间。空格是32,而不是0

发生的情况是您使用的是宽字符终端,但将其读取为字节,因此您看到的是 UTF-16-LE 字节。在 UTF-16-LE 中,a 是两个字节,970。如果您将它们视为两个 ASCII 字符而不是一个 UTF-16-LE 字符来阅读,您将得到a,后跟\0

请注意,您返回的实际上不是'a\0a\0a\0',而是b'a\0a\0a\0'。所以您可以将这些缓存到bytesbytearray 并在其上使用decode('utf-16-le')。但这违背了一次读取一个字符的目的。

最简单的解决方法是使用getwch 而不是getch。这将主要做你想做的事——返回一个像'a' 这样的单字符str 值,而不是两个单独的单字节bytes 值。

星体字符(U+FFFF 以上的所有字符)显示为两个单独的代理而不是单个字符可能仍然存在一些问题,并且“特殊键”仍将显示为 Unicode U+0000U+00E0后跟一个键码(或者,如果你有一个较旧的 Python,可能是一个损坏的U+E0xx,键码嵌入在字符中)。但除此之外,它会按您预期的方式工作。

【讨论】:

  • getch 调用ReadConsoleInputA,返回根据控制台当前输入代码页编码的键盘输入,默认为OEM,不能设置为UTF-16LE(代码页1200)。 OP 的 C 运行时版本中存在错误,或者控制台本身存在错误(在 Windows 10 中更频繁,因为 MS 正在积极更新控制台代码),或者某些行为不端的库或备用终端(例如 ConEmu)有在当前进程中钩住ReadConsoleInputA
  • @eryksun ConEmu 可能是一种可能性——但老实说,我不知道如何引导他诊断他是如何搞砸控制台的。我认为这可能是超级用户的问题,而不是 SO。无论他做了什么,他都从控制台获取 UTF-16-LE,使用getwch 将解决他的 Python 问题,而且他没有询问其他问题……但如果你认为你可以诊断出根本问题,那将变得更好。
  • 我不认为 Stack Exchange Q & A 格式最适合解决可能由广泛问题引起的错误。我以前就走这条路,它基本上变成了持续页面的长时间聊天,它基本上也兼作使用调试器和其他工具的教程。
  • 许多字符(例如“∫”)在控制台中粘贴时将被忽略。如果粘贴的字符不在键盘映射中 (VkKeyScan) 或不是 C3_ALPHA 语言 (GetStringType) 或不在东亚全角范围内,则控制台将其粘贴为OEM Alt+Numpad 序列(或非BMP 的两个序列),即编码为OEM(通常为默认的“?”),转换为十进制字符串,并插入一系列按键事件。 Alt 键的最终键具有实际的 Unicode 字符值。 CRT getwch 函数不支持此粘贴的键事件序列。
  • 请注意,此 Alt+Numpad 键事件序列仅在低级别的 ReadConsoleInput 调用中观察到,正如 getwch 使用的那样。对于高级 ReadConsoleReadFile 调用,控制台仅包含实际的 Unicode 字符(或非 BMP 的代理对)。
猜你喜欢
  • 2014-04-17
  • 1970-01-01
  • 2014-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-02
相关资源
最近更新 更多