In this tutorial, I’ll show you how you can open and read a text file using command line arguments.
First, create a file called names.txt with a list of names.
To open a file using argparse, first, you have to create code that will handle parameters you can enter from the command line.
1 2 3 4 5 6 7 |
import argparse parser = argparse.ArgumentParser() parser.add_argument('filename', type=argparse.FileType('r')) args = parser.parse_args() print(args.filename.readlines()) |
In our case, the parameter that we pass on the command line is the file name, and it looks like this:
python test.py names.txt
Make sure that the Python and text files are in the same directory, otherwise, you have to supply the full path to these files.
If you run this code without a parameter, it will display the following message:
D:>python test.py usage: test.py [-h] filename test.py: error: the following arguments are required: filename
Now, let’s try to run this with a file name as an argument.
D:>python test.py names.txt ['Liam\n', 'Noah\n', 'William\n', 'James\n', 'Logan']
All the lines are displayed inside a single line with the newline characters ‘\n’. Let’s modify this, so each line of the text file is displayed as a single line on the console.
1 2 3 4 5 6 7 8 |
import argparse parser = argparse.ArgumentParser() parser.add_argument('filename', type=argparse.FileType('r')) args = parser.parse_args() for file in args.filename: print(file.strip()) |
The strip function inside the loop removes the newline characters.
D:>python test.py names.txt Liam Noah William James Logan
Without this function, the names would be displayed with two newline characters each: one from the text file and one from the for loop.
An alternative way to achieve the same result is to replace the for loop with the with keyword and the read function, instead of strip.
1 2 |
with args.filename as file: print(file.read()) |
Check if File Exists
If we use a file name as a parameter, you have to enter the one that exists, otherwise, the program will result in an error message:
D:>python test.py names1.txt usage: test.py [-h] filename test.py: error: argument filename: can't open 'names1.txt': [Errno 2] No such file or directory: 'names1.txt'
To deal with it, we have to handle this parameter and check whether the file exists before reading its content. For this task, we are going to import the sys library and the exists function.
Additionally, we have to handle the parameters that a user entered.
So, there are 4 options to handle:
- The file exists.
- The file doesn’t exist.
- Too few arguments.
- Too many arguments.
The code is going to look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import os.path import sys if len(sys.argv) == 2: if os.path.exists(sys.argv[1]): with open(sys.argv[1]) as file: print(file.read()) else: print('No such file') elif len(sys.argv) < 2: print('Too few arguments') else: print('Too many arguments') |
The len(sys.argv) checks how many parameters a user entered. 1 is a file name, 2 is a file name and a parameter, 3 is a file name and two parameters, etc.
This is the result of all 4 types of options:
D:>python test.py names.txt Liam Noah William James Logan D:>python test.py names1.txt No such file D:>python test.py Too few arguments D:>python test.py names.txt animals.txt Too many arguments
Handling multiple files
Let’s handle multiple files. If a user enters multiple files, all of them should be checked, instead of returning the “Too many arguments” error.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import os.path import sys args_num = len(sys.argv) if args_num > 1: for i in range(1, args_num): if os.path.exists(sys.argv[i]): with open(sys.argv[i]) as file: print(file.read()) else: print('No such file') else: print('Too few arguments') |
Now, if you run this code, Python will return this result.
D:>python test.py names.txt animals.txt Liam Noah William James Logan dog cat pig elephant
Handling Different File Types
Additionally, we can try to handle different types of files. In this code, we are going to read only text files and return error messages if a person tries to add the wrong type.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import os.path import sys args_num = len(sys.argv) if args_num > 1: for i in range(1, args_num): if os.path.exists(sys.argv[i]): if sys.argv[i].endswith('.txt'): with open(sys.argv[i]) as file: print(file.read()) else: print('Wrong file extension') else: print('No such file') else: print('Too few arguments') |
If you run the code, you’ll notice that an existing file with the wrong file extension is going to return a different message than before.
D:>python test.py names.txt animals.txt file.bat nofile.txt Liam Noah William James Logan dog cat pig elephant Wrong file extension No such file