23

I have been googling almost an hour and am just stuck.

for a script, stupidadder.py, that adds 2 to the command arg.

e.g. python stupidadder.py 4

prints 6

python stupidadder.py 12

prints 14

I have googled so far:

import argparse
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('x', metavar='x', type=int, nargs='+',
                    help='input number')

...

args = parser.parse_args()
print args
x = args['x']  # fails here, not sure what to put
print x + 2

I can't find a straightforward answer to this anywhere. the documentation is so confusing. :( Can someone help? Please and thank you. :)

user1601118
  • 397
  • 1
  • 2
  • 6

6 Answers6

40

Assuming that you are learning how to use the argparse module, you are very close. The parameter is an attribute of the returned args object and is referenced as x = args.x.

import argparse
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('x', metavar='x', type=int, nargs='+',
                    help='input number')

...

args = parser.parse_args()
print args
#x = args['x']  # fails here, not sure what to put
x = args.x
print x + 2
tdelaney
  • 73,364
  • 6
  • 83
  • 116
14

A sample run in Ipython with your code, showing that args is a simple object, not a dictionary. In the argparse code the namespace is accessed with getattr and setattr

In [4]: args=parser.parse_args(['12','4','5'])
In [5]: args
Out[5]: Namespace(x=[12, 4, 5])
In [6]: args['x']
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-3867439e1f91> in <module>()
----> 1 args['x']
TypeError: 'Namespace' object is not subscriptable
In [7]: args.x
Out[7]: [12, 4, 5]
In [8]: getattr(args,'x')
Out[8]: [12, 4, 5]
In [9]: sum(getattr(args,'x'))
Out[9]: 21

vars() can be used to turn the namespace into a dictionary.

In [12]: vars(args)['x']
Out[12]: [12, 4, 5]

Review the Namespace section of the argparse documentation.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • 2
    Being honest, I'd -1 for the scary first part (imo, haha) and +1 for the `vars` trick that is very useful if one requires a dict. – jeromej Dec 11 '14 at 12:50
2

You should simply do something like this:

x = args.x
2

As you are manipulating directly args Namespace object as if it were a dictionnary, it raises a

TypeError: 'Namespace' object is not subscriptable

My quick, personnal and ugly workaround is to access to the internal dict using internal __dict__ type

user_args = args.__dict__

This is quite usefull if you need to iterate over the arguments and filter it

c24b
  • 5,278
  • 6
  • 27
  • 35
  • 1
    `vars()` is better. https://stackoverflow.com/questions/16878315/what-is-the-right-way-to-treat-argparse-namespace-as-a-dictionary – cbmanica May 31 '21 at 18:45
  • I strongly disagree. – c24b Jun 09 '21 at 23:12
  • Why? (actual question, as I thought I was providing a useful answer) – cbmanica Jun 10 '21 at 16:38
  • Using global vars can have strong hidden side effects and lack of readabilty. Basically we don't exactly know what we manipulate. Using global variable is considered as a bad practise beside the fact that you can do it in a more readable and cleaner way... I don't pretend my answer is the better but vars() is hackish. – c24b Jun 10 '21 at 20:04
0

It might also be that you have multiple word variable like (with a dash here): parser.add_argument('-d', '--extracted-dir', type=str,...

To access it you can use: args.extracted_dir

You probably tried doing args['extracted-dir'] and that's why you got the error.

funerr
  • 7,212
  • 14
  • 81
  • 129
-2

I'm not entirely sure what your goal is. But if that's literally all you have to do, you don't have to get very complicated:

import sys
print int(sys.argv[1]) + 2

Here is the same but with some nicer error checking:

import sys

if len(sys.argv) < 2:
    print "Usage: %s <integer>" % sys.argv[0]
    sys.exit(1)

try:
    x = int(sys.argv[1])
except ValueError:
    print "Usage: %s <integer>" % sys.argv[0]
    sys.exit(1)

print x + 2

Sample usage:

C:\Users\user>python blah.py
Usage: blah.py <integer>

C:\Users\user>python blah.py ffx
Usage: blah.py <integer>

C:\Users\user>python blah.py 17
19
Claudiu
  • 224,032
  • 165
  • 485
  • 680
  • 1
    Thanks! For whatever reason, the examples in the python documentation don't mention this at all. http://docs.python.org/2/library/argparse.html The text does in passing, but I'd expect something more readable / usable from this python page. – user1601118 Jul 29 '13 at 21:10