Search code examples
pythonpython-3.xshellcmdfile-io

Reading input file to Python script, using CMD


I have following issue. I would like to read input from file (e.g. example.txt) to my Python script (e.g. script.py). Right now, I've implemented following lines of code:

import sys
with open(sys.argv[1], 'r') as f:
    contents = f.read()

And, when I want to read file to this script, I just need to type following line in CMD:

python script.py example.txt

And of course, it works properly. File example.txt is read by script.py, it can be checked by adding simple print(contents) line to script.py.

The problem is, I have to run this code in CMD just like that:

script.py < example.txt

So, the question is, how can I achieve that? I suppose, it depends on the OS. On my Windows 10, I'm getting an error:

Traceback (most recent call last):
File "script.py", line 2, in <module>
with open(sys.argv[1], 'r') as f:
IndexError: list index out of range

I'm not asking for solution (but it would be nice), but I just want to know where should I'm looking for a solution.


Solution

  • script.py < example.txt sends the file contents to stdin which can be accessed via sys.stdin. The following works:

    import sys
    
    # First try supporting commands formatted like: script.py example.txt
    if len(sys.argv) > 1:
        with open(sys.argv[1]) as f:
            contents = f.read()
    # Now try supporting: script.py < example.txt
    elif sys.stdin:
        contents = ''.join(sys.stdin)
    # If both methods failed, throw a user friendly error
    else:
        raise Exception('Please supply a file')
    
    print(contents)
    

    But in good old Python fashion, there is a built-in library that can make our life very easy. The library is fileinput, and it will automatically support both methods of reading input that you mentioned:

    import fileinput
    contents = fileinput.input()
    print( ''.join(contents) )
    

    And that works regardless of if you do script.py example.txt or script.py < example.txt or cat example.txt | script.py and you can even do script.py example1.txt example2.txt example3.txt and you will receive the file contents of the different files combined together.