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.
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.