gpt4 book ai didi

python - 如何在不等待输入的情况下检查可能为空的标准输入?

转载 作者:太空宇宙 更新时间:2023-11-03 15:11:18 24 4
gpt4 key购买 nike

我试图在不等待输入的情况下读取键盘输入。目的是在“无限”循环中使用,也就是 while True:

到目前为止,我一直在尝试操作 readcharhttps://pypi.python.org/pypi/readchar/0.6 ,但没有运气。虽然它不等待 Enter,但它仍会等待一些输入。我不希望它等待输入,而只是检查并返回 "" 或一些占位符(如果没有输入)。

这是我一直在使用的:

def readchar():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch

def main():
while True:
current = readchar()
if current == "some letter":
print("things happen")

最佳答案

最终构成 Python 文件对象基础的 POSIX I/O 函数有两种不同的模式,阻塞和非阻塞,由名为 O_NONBLOCK 的标志控制。 .特别是 read功能说:

When attempting to read a file … that … has no data currently available … If O_NONBLOCK is set, read() shall return -1 and set errno to [EAGAIN].

在 Python 中,这个标志在 os 中可用。模块。


sys.stdin 已经打开,所以你不能只将 O_NONBLOCK 传递给 os.open 函数,所以……怎么办你做?好吧,您实际上可能想要打开/dev/tty;这在某种程度上取决于您实际在做什么。在那种情况下,答案是显而易见的。但是让我们假设你没有。因此,您想更改已打开文件的标志。这正是fcntl是为了。您使用 F_GETFL 操作来读取当前标志,或者在 O_NONBLOCK 的位中,以及 F_SETFL 结果。当然,如果您想恢复内容,您可以记住当前标志以备后用。

在 Python 中,fcntl 函数和操作常量在 fcntl 中可用。模块。


最后一个问题:sys.stdin 不是原始文件对象,它是 TextIOWrapperBufferedReader 之上进行 Unicode 解码,它本身在 FileIO 之上添加了缓冲.所以,sys.stdin.read() 并不是直接调用 POSIX read 函数。为此,您需要使用 sys.stdin.buffer.raw。如果您想在原始输入和正常输入之间来回切换,您可能还需要进行大量仔细的冲洗。 (请注意,这意味着您要放弃 Unicode,取而代之的是获得单字节 bytes 对象,例如,它可能是 UTF-8 字符的一半或终端转义字符的四分之一。希望您对此有所期待。)


现在,当没有可用内容时,FileIO.read 返回什么?好吧,它是 RawIOBase 的实现,并且 RawIOBase.read说:

If 0 bytes are returned, and size was not 0, this indicates end of file. If the object is in non-blocking mode and no bytes are available, None is returned.

换句话说,如果没有可用的,你将得到None,对于EOF,你将得到b'',或者一个单字节的bytes 用于其他任何内容。


所以,把它们放在一起:

old_settings = termios.tcgetattr(fd)
old_flags = fcntl.fcntl(fd, fcntl.F_GETFL)
try:
tty.setraw(fd)
fcntl.fcntl(fd, fcntl.F_SETFL, old_flags | os.O_NONBLOCK)
return sys.stdin.buffer.raw.read(1)
finally:
fcntl.fcntl(fd, fcntl.F_SETFL, old_flags)
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)

最后一件事:有没有办法在不读取输入的情况下判断输入是否准备就绪?是的,但不是便携的。根据您的平台,selectpollepoll 和/或 kqueue 可能可用并且可以在常规文件。 read(0) 可以保证返回 b'' 而不是 None。等等。您可以阅读本地手册页。但更简单的解决方案与 C 的 stdio 所做的相同:添加一个 1-byte-max 缓冲区,并使用它来实现您自己的 readpeekread unread 包装器。

关于python - 如何在不等待输入的情况下检查可能为空的标准输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26263636/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com