Hello, this is my first post I’d like to share a recurring frustration with the argparse library.
Sometimes I need to check whether an argument is a file or not. The simpler approach is to use os.path.isfile, but I don’t like setting up exceptions when the argument is not a file:
parser.add_argument("file")
args = parser.parse_args()
if not os.path.isfile(args.file):
raise ValueError("NOT A FILE!")
What I like to do instead is to use argparse.FileType:
parser.add_argument("file", type=argparse.FileType("r"))
args = parser.parse_args()
args.file.close() # WHYYY!
args.file.name # This is what I need
It handles the errors for me, which is nice, but it also gives-me an open io.TextIOWrapper that I have to close manually when I don’t need the stream.
What I’d like to write is something like this:
parser.add_argument("file", type=argparse.IsFile(extension="h5"))
args = parser.parse_args()
args.file # A nice path for an existing .h5 file!
What do you guys think? Do any of you have the same problem?
It’s not something I’ve ever been particularly bothered about, but argparse is designed to allow you to write your own type-checking functions exactly like this, so it certainly seems like something you could write, either for your own application, or as a common library (maybe containing various type checkers you find useful).
Whether this particular example is sufficiently useful to warrant adding to the stdlib, I honestly don’t know.
I have several argparse type functions I accumulated from various projects, and I’m sure there are many others with the similar collections. Maybe It’d be a good idea to make a package (say argparse-types) so they can be readily accessible. Something like Path(file=Ture, exists=True) would fit your need here.
usage: test.py [-h] number json path
do stuff
positional arguments:
number Integer 0-10
json JSON formatted string
path File path (new file)
optional arguments:
-h, --help show this help message and exit
And also has better error handling for parsing the arguments instead of a stack trace
$ ./test.py '{key: "value"} ' # missing quotes on "key"
Argument "json" expecting property name enclosed in double quotes: line 1 column 2 (char 1)
$ ./test.py 22 # wrong range
Argument "number" should be in range 0-10
That would be great. There is just one essential problem with paths (when we need existing ones). They must exist at the time we are opening them. The time of parsing the arguments is less important. So you would need to handle the errors related to path existence twice.