type=dict in argparse.add_argument()

后端 未结 11 703
既然无缘
既然无缘 2020-12-03 07:02

I\'m trying to set up a dictionary as optional argument (using argparse); the following line is what I have so far:

parser.add_argument(\'-i\',\'--image\', t         


        
11条回答
  •  旧巷少年郎
    2020-12-03 07:31

    You can definitely get in something that looks like a dictionary literal into the argument parser, but you've got to quote it so when the shell parses your command line, it comes in as

    • a single argument instead of many (the space character is the normal argument delimiter)
    • properly quoted (the shell removes quotes during parsing, because it's using them for grouping)

    So something like this can get the text you wanted into your program:

    python MYSCRIPT.py -i "{\"name\": \"img.png\", \"voids\": \"#00ff00ff\",\"0\": \"#ff00ff00\",\"100%\": \"#f80654ff\"}"
    

    However, this string is not a valid argument to the dict constructor; instead, it's a valid python code snippet. You could tell your argument parser that the "type" of this argument is eval, and that will work:

    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('-i','--image', type=eval, help='Generate an image map...')
    args = parser.parse_args()
    print args
    

    and calling it:

    % python MYSCRIPT.py -i "{\"name\": \"img.png\", \"voids\": \"#00ff00ff\",\"0\": \"#ff00ff00\",\"100%\": \"#f80654ff\"}"
    Namespace(image={'0': '#ff00ff00', '100%': '#f80654ff', 'voids': '#00ff00ff', 'name': 'img.png'})
    

    But this is not safe; the input could be anything, and you're evaluating arbitrary code. It would be equally unwieldy, but the following would be much safer:

    import argparse
    import ast
    
    parser = argparse.ArgumentParser()
    parser.add_argument('-i','--image', type=ast.literal_eval, help='Generate an image map...')
    args = parser.parse_args()
    print args
    

    This also works, but is MUCH more restrictive on what it will allow to be eval'd.

    Still, it's very unwieldy to have the user type out something, properly quoted, that looks like a python dictionary on the command line. And, you'd have to do some checking after the fact to make sure they passed in a dictionary instead of something else eval-able, and had the right keys in it. Much easier to use if:

    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument("--image-name", required=True)
    parser.add_argument("--void-color", required=True)
    parser.add_argument("--zero-color", required=True)
    parser.add_argument("--full-color", required=True)
    
    args = parser.parse_args()
    
    image = {
        "name": args.image_name,
        "voids": args.void_color,
        "0%": args.zero_color,
        "100%": args.full_color
        }
    print image
    

    For:

    % python MYSCRIPT.py --image-name img.png --void-color \#00ff00ff --zero-color \#ff00ff00 --full-color \#f80654ff
    {'100%': '#f80654ff', 'voids': '#00ff00ff', 'name': 'img.png', '0%': '#ff00ff00'}
    

提交回复
热议问题