[英]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.stdin
的read
方法比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.