Skip to content

Read from stdin or pipe

Ariel Balter edited this page Jan 4, 2017 · 2 revisions

http://stackoverflow.com/a/31973024/188963

This is how I ended up doing this. I didn't really like any of the other solutions, they didn't seem very pythonic.

This will make a container for any open file input to iterate over all the lines. This will also take care of closing the file at the end of the context manager.

I feel like this is probably how the for line in sys.stdin: block should operate by default.

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

From the command line both of the following should work:

tail -f /var/log/debug.log | python fileinput.py
cat /var/log/debug.log | python fileinput.py

http://stackoverflow.com/a/1454400/188963

You could use the fileinput module:

import fileinput

for line in fileinput.input():
    pass

fileinput will loop through all the lines in the input specified as file names given in command-line arguments, or the standard input if no arguments are provided.

I would strongly recommend against using argparse's parse_known_args() unless you have a strong reason to do so as it will accept pretty much any option or argument (including -- or --typo) without error and force you to manually parse them later. I would use something like the following instead: parser.add_argument(action='append', dest='files', nargs='*'). You can then access the list of files like so: options = parser.parse_args(args) files = options.files[0]

Clone this wiki locally