当管道来自“打开”(不知道正确的名称)时,我在python中读取标准输入或管道时遇到问题 文件。
我有例子 的 pipetest.py:
import sys
import time
k = 0
try:
for line in sys.stdin:
k = k + 1
print line
except KeyboardInterrupt:
sys.stdout.flush()
pass
print k
我运行一个继续输出的程序,一段时间后再按Ctrl + c
$ ping 127.0.0.1 | python pipetest.py
^C0
我没有输出。 但如果我通过一个普通的文件,它可以工作。
$ ping 127.0.0.1 > testfile.txt
在短时间内按Ctrl + c结束
$ cat testfile.txt | python pipetest.py
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.017 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.015 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.014 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.013 ms
64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.012 ms
--- 127.0.0.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3998ms
rtt min/avg/max/mdev = 0.012/0.014/0.017/0.003 ms
10
如何在程序结束前获取任何输出,在这种情况下ping已结束?
答案 0 :(得分:25)
尝试下一个:
import sys
import time
k = 0
try:
buff = ''
while True:
buff += sys.stdin.read(1)
if buff.endswith('\n'):
print buff[:-1]
buff = ''
k = k + 1
except KeyboardInterrupt:
sys.stdout.flush()
pass
print k
答案 1 :(得分:7)
k = 0
try:
while True:
print sys.stdin.readline()
k += 1
except KeyboardInterrupt:
sys.stdout.flush()
pass
print k
答案 2 :(得分:7)
为了让它在不等待stdin流结束的情况下工作,你可以在readline上进行操作。我认为这是最简单的解决方案。
import sys
k = 0
try:
for line in iter(sys.stdin.readline, b''):
k = k + 1
print line
except KeyboardInterrupt:
sys.stdout.flush()
pass
print k
答案 3 :(得分:3)
虽然sys.stdin是一个类似文件的对象,意味着你可以迭代它的行,它将阻塞直到插入一个EOF。
可以使用以下伪代码描述行为:
while True:
input = ""
c = stdin.read(1)
while c is not EOF:
input += c
c = stdin.read(1)
for line in input.split('\n'):
yield line
这意味着,虽然您可以迭代sys.stdin的行,但您不能将此方法用于手头的任务,您必须显式调用read()或readline()
答案 4 :(得分:3)
这就是我最终做到这一点的方式。我并不喜欢任何其他解决方案,它们似乎不是非常pythonic。
这将使任何打开文件输入的容器迭代所有行。这也将负责关闭上下文管理器末尾的文件。
我觉得这可能是for line in sys.stdin:
块默认运行的方式。
class FileInput(object):
def __init__(self, file):
self.file = file
def __enter__(self):
return self
def __exit__(self, *args, **kwargs):
self.file.close()
def __iter__(self):
return self
def next(self):
line = self.file.readline()
if line == None or line == "":
raise StopIteration
return line
with FileInput(sys.stdin) as f:
for line in f:
print f
with FileInput(open('tmpfile') as f:
for line in f:
print f
从命令行,以下两项都应该有效:
tail -f /var/log/debug.log | python fileinput.py
cat /var/log/debug.log | python fileinput.py