94

I want to open file for reading using argparse. In cmd it must look like: my_program.py /filepath

That's my try:

parser = argparse.ArgumentParser()
parser.add_argument('file', type = file)
args = parser.parse_args()

This gives me [edit: added later from comment by OP]:

parser.add_argument('file', type = file) NameError: name 'file' is not defined
5
  • 5
    And it did what, exactly? Commented Sep 18, 2013 at 2:17
  • What is your problem currently? Commented Sep 18, 2013 at 2:31
  • Running this i have error: parser.add_argument('file', type = file) NameError: name 'file' is not defined I don't exaclty understand how argparse work... Commented Sep 18, 2013 at 2:38
  • 1
    type = fnc works if fnc is a function that takes a string, and returns a desired object, or raises an error. There isn't a file function in Python. type=open does work since there is a Python function open(filename)'. argparse provides a better function, argparse.FileType()` (actually a function constructor). But a simple string argument as in wims answer is a better starting place. Commented Sep 18, 2013 at 3:53
  • 4
    type=file does work in Python2.7 (and earlier). But in Python3, file has been removed. stackoverflow.com/questions/112970/… Commented Sep 19, 2013 at 5:16

7 Answers 7

231

Note: argparse.FileType, which this answer mentions, has now been deprecated. See gh-58032: argparse.FileType opens a file and never closes it.

Python < 3.13:

Take a look at the documentation: https://docs.python.org/3/library/argparse.html#type

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('file', type=argparse.FileType('r'))
args = parser.parse_args()

print(args.file.readlines())
Sign up to request clarification or add additional context in comments.

15 Comments

@L0j1k Whilst I feel it is good to have both answers here, one should also mention the caveats of argparse.FileType. For example, it leaves an open file handle dangling which is in my opinion sloppy implementation. Usually I would rather be handling the file open() myself so that I can do it properly (with a context manager), and also customise the behaviour and output for 'file not found' errors.
p.s. there is an issue on the python bug tracker about this, and python devs have commented that "FileType is not what you want for anything but quick scripts that can afford to either leave a file open or to close stdin and/or stdout"
Indeed, that changes everything.
You can do with args.file as f: ... which will close the file earlier in the good scenario case.
@Wernight: But argparse automatically sets file to <stdin> (or <stdout>, depending on mode) if the argument is missing or is -. Which is a very cool feature, but if with args.file as f: ... is used, it will (or try to) close them, when it shouldn't.
|
111

The type of the argument should be string (which is default anyway). So make it like this:

parser = argparse.ArgumentParser()
parser.add_argument('filename')
args = parser.parse_args()

with open(args.filename) as file:
    # do stuff here

3 Comments

Please see wim's comments under ilent2's answer for the reasons why this answer is probably the best answer in most cases.
You shouldn't use the variable name file since that is a built-in.
Generally that is correct, but file is never used in python these days - it was removed in python3, and in python2 the docstring even advises to use open instead. So it's OK to stomp this name, it is even done several times in core libraries.
42

In order to have the file closed gracefully, you can combine argparse.FileType with the with statement

parser.add_argument('file', type=argparse.FileType('r'))
args = parser.parse_args()

with args.file as file:
    print(file.read())

4 Comments

In the line with args.file the "file" refers to the name of the argument right? If I had named the argument as -f then it should be with args.-f right?? Correct me if I'm wrong. Argparse beginner here
@vishal.k Yes and no. If you do add_argument('-f', ..., then you need with args.f as file without the dash
By using type=argparse.FileType('r'), the file is opened from the point you call parser.parse_args(). Does this mean the file would still be left open if your code crashes before your context handler? Not a big deal, but something to keep in mind.
Note: argparse.FileType has been deprecated in Python 3.14.
37

I'll just add the option to use pathlib:

import argparse, pathlib

parser = argparse.ArgumentParser()
parser.add_argument('file', type=pathlib.Path)
args = parser.parse_args()

with args.file.open('r') as file:
    print(file.read())

Comments

12

TL; DR

parser.add_argument(
    '-f', '--file',
    help='JSON input file',
    type=argparse.FileType('r'),
)

Description

Simple command line script to reformat JSON files

reformat-json \
    -f package.json \
    --indent=2 \
    --sort-keys \
    --output=sorted_package.json

can be code in Python as follows

#!/usr/bin/env python3

import argparse, json, sys

EXIT_SUCCESS = 0
EXIT_FAILURE = 1

def main():
    parser = argparse.ArgumentParser()

    parser.add_argument(
        '-f', '--file',
        help='JSON input file',
        type=argparse.FileType('r'),
    )

    parser.add_argument(
        '-i', '--indent',
        help='Non-negative integer indent level',
        type=int
    )

    parser.add_argument(
        '-o', '--output',
        help='Write JSON into output file',
        type=argparse.FileType('w'),
    )

    parser.add_argument(
        '-s', '--sort-keys',
        action='store_true',
        help='Sort output JSON by keys',
    )

    args = parser.parse_args()

    if not args.file:
        parser.print_usage()
        return sys.exit(EXIT_FAILURE)

    gson = json.dumps(
        json.load(args.file),
        indent=args.indent,
        sort_keys=args.sort_keys
    )

    args.file.close()

    if args.output:
        args.output.write(gson)
        args.output.write('\n')
        args.output.close()
    else:
        print(gson)

    return sys.exit(EXIT_SUCCESS)

if __name__ == '__main__':
    main()

1 Comment

Note: argparse.FileType has been deprecated in Python 3.14.
0

The following avoids the problems with closing files correctly that are present in ilent2's answer. It works with multiple file arguments and resembles the argparse.FileType approach.

import argparse
import contextlib

class FileStack(contextlib.ExitStack):
    def file(self, mode):
        def _open(path):
            obj = open(path, mode)
            self.enter_context(obj)
            return obj
        return _open

with FileStack() as stack:
    parser = argparse.ArgumentParser()
    parser.add_argument("file", type=stack.file("r"))
    args = parser.parse_args()

    args.file.read()
# Here, args.file is correctly closed

Comments

-2

This implementation allows the "file name" parameter to be optional, as well as giving a short description if and when the user enters the -h or --help argument.

parser = argparse.ArgumentParser(description='Foo is a program that does things')
parser.add_argument('filename', nargs='?')
args = parser.parse_args()

if args.filename is not None:
    print('The file name is {}'.format(args.filename))
else:
    print('Oh well ; No args, no problems')

1 Comment

It doesn't answer the question at all. OP was asking how they could open a file for reading with argparse, not check that the user specified a filename.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.