簡體   English   中英

Python select()行為很奇怪

[英]Python select() behavior is strange

我在理解select.select的行為時遇到了一些麻煩。 請考慮以下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)

我已將其保存到文件“test.py”。 如果按如下方式調用它:

echo 'hello' | ./test.py

然后我得到了預期的行為:選擇never塊並打印所有數據; 程序然后終止。

但如果我以交互方式運行程序,我會得到一個最不受歡迎的行為。 請考慮以下控制台會話:

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

程序然后掛在那里; select.select現在再次阻止。 直到我提供更多輸入或關閉輸入流,即使已經有字符在等待,也會打印下一個字符(以及其余所有字符)! 任何人都可以向我解釋這種行為嗎? 我在一個我編寫的流隧道程序中看到了類似的東西,它破壞了整個事件。

謝謝閱讀!

sys.stdinread方法比select更高的抽象級別。 當您執行ans[0].read(1) ,python實際上從操作系統讀取更多的字節並在內部緩沖它們。 select不知道這個額外的緩沖; 它只會看到所有內容都已被讀取,因此會阻止,直到EOF或更多輸入到達。 您可以通過運行類似strace -e read,select python yourprogram.py來觀察此行為。

一種解決方案是用os.read(ans[0].fileno(), 1)替換ans[0].read(1) os.read(ans[0].fileno(), 1) os.read是一個較低級別的接口,它與操作系統之間沒有任何緩沖,所以它更適合select

或者,使用-u命令行選項運行python似乎也禁用了額外的緩沖。

它正在等待您發出EOF信號(交互使用時,您可以使用Ctrl + D執行此操作)。 您可以使用sys.stdin.isatty()來檢查腳本是否以交互方式運行,並相應地使用say 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)

這將使其適用於交互式使用和流處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM