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

后端 未结 3 1437
日久生厌
日久生厌 2021-02-07 17:05

Let\'s say I have a script that does some work on a file. It takes this file\'s name on the command line, but if it\'s not provided, it defaults to a known filename (conte

相关标签:
3条回答
  • 2021-02-07 17:29

    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.

    0 讨论(0)
  • 2021-02-07 17:44

    Use stdin as default:

    parser.add_argument('file', default='-', nargs='?', type=argparse.FileType('r'))
    
    0 讨论(0)
  • 2021-02-07 17:49

    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.

    0 讨论(0)
提交回复
热议问题