Specifying default filenames with argparse, but not opening them on --help?

北战南征 提交于 2019-12-03 05:47:42

Looking at the argparse code, I see:

  • ArgumentParser.parse_args calls parse_known_args and makes sure that there isn't any pending argument to be parsed.
  • ArgumentParser.parse_known_args sets default values and calls ArgumentParser._parse_known_args

Hence, the workaround would be to use ArgumentParser._parse_known_args directly to detect -h and, after that, use ArgumentParser.parse_args as usual.

import sys, argparse
parser = argparse.ArgumentParser(description='my illustrative example', argument_default=argparse.SUPPRESS)
parser.add_argument('--content', metavar='file',
                     default='content.txt', type=argparse.FileType('r'),
                     help='file to process (defaults to content.txt)')
parser._parse_known_args(sys.argv[1:], argparse.Namespace())
args = parser.parse_args()

Note that ArgumentParser._parse_known_args needs a couple of parameters: the arguments from the command line and the namespace.

Of course, I wouldn't recommend this approach since it takes advantage of the internal argparse implementation and that might change in the future. However, I don't find it too messy, so you still might want to use it if you think maintenance risks pay off.

You could subclass argparse.FileType:

import argparse
import warnings

class ForgivingFileType(argparse.FileType):
    def __call__(self, string):
        try:
            super(ForgivingFileType,self).__call__(string)
        except IOError as err:
            warnings.warn(err)

parser = argparse.ArgumentParser(description='my illustrative example')
parser.add_argument('--content', metavar='file', 
                     default='content.txt', type=ForgivingFileType('r'),
                     help='file to process (defaults to content.txt)')
args = parser.parse_args()

This works without having to touch private methods like ArgumentParser._parse_known_args.

Use stdin as default:

parser.add_argument('file', default='-', nargs='?', type=argparse.FileType('r'))

Perhaps you could define your own type or action in the add_argument call that checks if the file exists, and returns a file handle if it does and None (or something else) otherwise.

This would require you to write some code of yourself as well though, but if the default value can not always be used you probably have to do some checking sooner or later. Like Manny D argues you might want to reconsider your default value.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!