9

I want to send arguments to script by their name (something like kwargs). I tried something like this but it's not doing what I want: (let's say it's written in script.py)

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("name")
args = parser.parse_args()

and then writing in commant line: script.py name = david

another thing, let's say I have few named argument in argparse If I will send them not in the order they are declared will it still work well?

davidmoshko
  • 223
  • 1
  • 4
  • 8

3 Answers3

25

The question as stated contains a bit of a misunderstanding, or I have a big one.

*keyword and **keyword are for passing parameters/stuff to classes/functions/methods INSIDE the python code.

argparse is used to pass arguments/options into the python program from outside/the commandline. So you're not going to get a 1 for 1 replication of it. However argparse is pretty configurable, and depending on how you want to do it you can come close.

If you only want to pass one name, then:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("name")
args = parser.parse_args()

print args

will let you:

$ ./pytest.py dave
Namespace(name='dave')

If you want to set name so you can send other stuff as well:

parser.add_argument("-name")

Will let you:

./pytest.py -name dave
Namespace(name='dave')

but notice:

 ./pytest.py -name dave -name steve
 Namespace(name='steve')

However:

parser.add_argument("--name")

will let/require:

./pytest.py --name dave
Namespace(name='dave')

./pytest.py --name=dave
Namespace(name='dave')

and if you:

parser.add_argument("--name", nargs="+")

./pytest.py --name dave steve murphy
Namespace(name=['dave', 'steve', 'murphy'])

But:

 ./pytest.py --name=dave --name=steve --name=murphy      
 Namespace(name=   ['murphy'])

(note that that last one is a list with only murphy in it.)

So what you could do is:

parser.add_argument("--name")
parser.add_argument("--email")
parser.add_argument("--hair-color")

./pytest.py --name fred --hair-color murphy --email example@example.com
Namespace(email='example@example.com', hair_color='murphy', name='fred')
Petro
  • 776
  • 6
  • 13
7

In argparse, and earlier command line processers of the same style, there's a distinction between 'optionals' or flagged arguments and positionals.

'optionals' are signaled by a flag string, something like -f or --foo. These are similar to the keyword arguments of Python functions, but not identical. The order does not matter. With in limits the flags can be joined to the values, e.g. -f1, --foo=astring.

'positionals' are identified by order, without any identifying name. These are similar to the args of Python functions. In functions, all positional args have to occur before keyword ones. With argparse 'optionals' can mixed with 'positionals' - with some limits. It's common to supply all positionals after the optionals, as indicated in the argparse usage message.

Look at the examples in the argparse documentation.

Periodically we get questions from people who want to circumvent these conventions, for example expecting to use flag without the prefix characters, or to input dictionary like pairs, foo=test or foo:test. Some of this is possible, but it takes more work. And usually for little gain in clarity and usefulness.

I'd suggest passing script.py name = david to a script that just displays the sys.argv list. These are the values that argparse has to work with. I expect you will see:

['script.py', 'name', '=', 'david']

Your shell has split that commandline into separate strings. It is probably easier to do your own parsing of that list than it is to twist argparse into a form that will it.

Argparse can easily handle inputs like

script.py --name david
script.py --name=david
script.py david
hpaulj
  • 221,503
  • 14
  • 230
  • 353
0

Order doesn't matter.

Change your argument to

parser.add_argument('-name')

Also, what's wrong is your call from command line. It should look like this:

python script.py name david
ham_string
  • 139
  • 5