Как вы читаете из стандартного ввода в python из канала, у которого нет конца

У меня проблема с чтением из стандартного ввода или канала в 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 завершился?

]
24
задан Janne 17 August 2011 в 10:36
поделиться

1 ответ

Так я и сделал. Мне не очень понравились какие-либо другие решения, они не казались очень питонными.

Это создаст контейнер для любого ввода открытого файла, чтобы перебрать все строки. Это также позаботится о закрытии файла в конце диспетчера контекста.

Я чувствую, что, вероятно, именно так должен работать блок 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
4
ответ дан 28 November 2019 в 23:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: