24

Using the type parameter of the argparse.add_argument method, you can require an argument to be a readable file:

parser.add_argument('--sqlite-file', type=argparse.FileType('r'))

As a benefit of specifying this type, argparse checks whether the file can be read and displays an error to the user if not.

Is there a way to obtain the passed filename instead of an instance of io.TextIOWrapper or io.BufferedReader?

Since the filename appears in the string representation of the parser ('sqlite_file': <_io.TextIOWrapper name='data/export.sqlite' ..., or 'sqlite_file': <_io.BufferedReader name='data/export.sqlite' ...>) it should be possible.

How to do it?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
jack_kerouac
  • 1,482
  • 2
  • 15
  • 30
  • http://bugs.python.org/issue13824 looks into the possibility of `FileTYpe` checking without actually opening the file. The solution I proposed there was to use `os.access` to test the filename. – hpaulj Oct 29 '13 at 21:53

1 Answers1

35

Yes, use the .name attribute on the file object.

Demo:

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--sqlite-file', type=argparse.FileType('r'))
_StoreAction(option_strings=['--sqlite-file'], dest='sqlite_file', nargs=None, const=None, default=None, type=FileType('r'), choices=None, help=None, metavar=None)
>>> args = parser.parse_args(['--sqlite-file', '/tmp/demo.db'])
>>> args.sqlite_file
<_io.TextIOWrapper name='/tmp/demo.db' mode='r' encoding='UTF-8'>
>>> args.sqlite_file.name
'/tmp/demo.db'
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • What will happen, if user will specify `FileType` argument as `-` to use the stdin or stdout? – Vasilly.Prokopyev Jul 27 '18 at 07:20
  • 1
    `FileType()` produces normal file objects for filenames, and `sys.stdin` or `sys.stdout` for `'-'`. Those two objects have `''` and `''` as their name attribute, respectively. – Martijn Pieters Jul 27 '18 at 09:33