Python select()行为是strang

2024-04-19 22:44:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我很难理解选择。选择. 请考虑以下Python程序:

def str_to_hex(s):
    def dig(n):
        if n > 9:
            return chr(65-10+n)
        else:
            return chr(48+n)
    r = ''
    while len(s) > 0:
        c = s[0]
        s = s[1:]
        a = ord(c) / 16
        b = ord(c) % 16
        r = r + dig(a) + dig(b)
    return r

while True:
    ans,_,_ = select.select([sys.stdin],[],[])
    print ans
    s = ans[0].read(1)
    if len(s) == 0: break
    print str_to_hex(s)

我已将此保存到一个文件中”测试.py". 如果按如下方式调用它:

^{pr2}$

然后我得到了预期的行为:selectnever块,所有的数据都被打印出来;然后程序终止。在

但如果我运行的是一个最不受欢迎的程序,我会以交互方式运行。请考虑以下控制台会话:

$ ./test.py
hello
[<open file '<stdin>', mode 'r' at 0xb742f020>]
68

然后程序挂在那里;选择。选择现在又阻塞了。直到我提供更多的输入或关闭输入流,下一个字符(以及其余字符)才会打印出来,即使已经有字符在等待!有人能向我解释一下这种行为吗?我在我写的一个流隧道程序中看到了类似的东西,它破坏了整个事件。在

谢谢你的阅读!在


Tags: to程序lenreturnifdef字符select
2条回答

sys.stdinread方法比select具有更高的抽象级别。当您执行ans[0].read(1)操作时,python实际上会从操作系统中读取大量字节,并在内部进行缓冲。select不知道这个额外的缓冲区;它只看到所有内容都已被读取,因此将阻塞,直到EOF或更多的输入到达。您可以通过运行strace -e read,select python yourprogram.py来观察这种行为。在

一种解决方案是将ans[0].read(1)替换为os.read(ans[0].fileno(), 1)os.read是一个较低级别的接口,在它和操作系统之间没有任何缓冲,因此它更适合{}。在

或者,使用-u命令行选项运行python似乎也会禁用额外的缓冲。在

它正在等待您向EOF发出信号(交互使用时,可以使用Ctrl+D来完成此操作)。您可以使用sys.stdin.isatty()检查脚本是否正在以交互方式运行,并相应地进行处理,例如使用raw_input。我也怀疑您是否需要使用select.select,为什么不直接使用sys.stdin.read?在

if sys.stdin.isatty():
    while True:
        for s in raw_input():
            print str_to_hex(s)
else:
    while True:
        for s in sys.stdin.read(1):
            print str_to_hex(s)

这使得它既适合交互使用,也适合流处理。在

相关问题 更多 >