Python在没有批处理的情况下读取unicode stdin

时间:2014-09-25 15:07:58

标签: python python-2.7 cpython

如果我在python中读取stdin的输入,for循环将在循环体运行之前收集许多行(至少在cpython中)。

from __future__ import print_function
import sys

for line in sys.stdin:
    print("Echo:", line.strip())

输出:

$ python ../test.py 
foo
bar
Echo: foo
Echo: bar

线条以某种批次处理。 我可以这样避免:

from __future__ import print_function
import sys

for line in iter(sys.stdin.readline, ''):
    print("Echo:", line.strip())

输出:

$ python ../test.py 
foo
Echo: foo
bar
Echo: bar

这就是我需要的。

我的问题是我必须阅读utf-8输入并使用iter()的技巧不能与codecs.getwriter一起使用。

from __future__ import print_function
import sys
import codecs

sys.stdin = codecs.getreader('utf-8')(sys.stdin)
for line in iter(sys.stdin.readline, ''):
    print("Echo:", line.strip())

$ python ../test.py 
foo
bar
Echo: foo
Echo: bar

从stdin读取utf8数据时有没有办法避免这种批处理?


编辑: 为完整性添加了import语句。

2 个答案:

答案 0 :(得分:1)

您应该使用raw_inputstdin获取一行输入。

try:
    while True:
        print("Echo:", raw_input())
except EOFError:
    pass

问题是Python 2只是有这种缓冲。请参阅联机帮助页上的-u文档

-u   Force  stdin,  stdout  and stderr to be totally unbuffered.  On systems
     where it matters, also put stdin, stdout and  stderr  in  binary  mode.
     Note  that there is internal buffering in xreadlines(), readlines() and
     file-object iterators ("for line in sys.stdin") which is not influenced
     by   this   option.   To  work  around  this,  you  will  want  to  use
     "sys.stdin.readline()" inside a "while 1:" loop.

重要的是使用sys.stdin.readline()是推荐的行动方案;它不太可能是强行取消缓冲文件对象的好方法。

你应该在得到它时解码每一行。

答案 1 :(得分:1)

使用lambda

for line in iter(lambda: sys.stdin.readline().decode('utf-8'), ''):
    print 'Echo:', line.strip()

或,在循环体中解码:

for line in iter(sys.stdin.readline, ''):
    print "Echo:", line.decode('utf-8').strip()