2

In Perl, One can easily read in multiple key=value pair into a variable (a hash) using Getopt::Long (see here )

Basically it says

 GetOptions ("define=s" => \%defines);
 And on command line: <prog> --define os=linux --define vendor=redhat

I have been looking an equivalent in Python but hasn't found any so far [argparse] doesn't take in dictionary from bash shell easily see type=dict in argparse.add_argument() . Although I can work around this by reading in the arguments and programmatically create a dictionary out of it, I just wanted to know a clean and simple way to do it (like Perl has)

2
  • An argparse style input would be more like: python stack18800328.py --os=linux --vendor=redhat. But that requires knowing the possible 'key' values ahead of time. Commented Sep 16, 2013 at 20:36
  • define as an append argument in argparse followed by this one liner is the most compact way I can think of: args.define = {k:v for k,v in (a.split('=') for a in args.define)} Commented Sep 16, 2013 at 21:04

1 Answer 1

4

Use argparse with a custom action:

import argparse
import copy


class DictAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        try:
            k, v = values.split("=", 1)
        except ValueError:
            raise argparse.ArgumentError(self, "Format must be key=value")

        # Implementation is from argparse._AppendAction
        items = copy.copy(argparse._ensure_value(namespace, self.dest, {}))  # Default mutables, use copy!
        items[k] = v
        setattr(namespace, self.dest, items)

# Usage:
parser = argparse.ArgumentParser()
parser.add_argument("--define", action=DictAction)

print parser.parse_args("--define k=v --define x=y".split())
# Gives
# Namespace(d={'x': 'y', 'k': 'v'})

print parser.parse_args("--define k=v --define x=y --define z".split())
# Gives
# usage: args.py [-h] [--define D]
# args.py: error: argument --define: Format must be key=value

Note that this won't support having an equals sign inside a parameter, but you can expand on the "dumb" k, v = values.split("=", 1) to address this.

Sign up to request clarification or add additional context in comments.

1 Comment

I know of this work-around [not exactly the way you have written though] and I have been using this. However, I just wanted to know if there is some python module already up there [like perl's getopt] that does it without adding extra lines. So far I found none. Thanks for the response though :)

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.