0

I have a method I call from the command line using argparse. I also want to call that method from another method, in this case I get an error saying args is not defined. Is there a way around this, I have tried setting a default but I get the same error.

def change_modem_bank(bank_num=None, modem=None):  
    if args.sim_bank and args.modem_num:
        bank_num = args.sim_bank
        modem = args.modem_num  
    if "1" in bank_num:
        print "2" 
    elif "2" in bank_num:
         print "2"
    print modem

if __name__=='__main__':            
    parser_mode = subparsers.add_parser('set_modem_bank')
    parser_mode.add_argument('-bank',dest='sim_bank',help='SIM bank number',nargs='?',const=None,default=None)
    parser_mode.add_argument('-modem_num',dest='modem_num',help='Modem number',nargs='?',const=None,default=None)
    parser_mode.set_defaults(func=change_modem_bank)
    args=parser.parse_args()
    args.func()

I want to call the method like so from another script:

import cellular_modem
cellular_modem.change_modem_bank("2","0")

Currently I can call it like this:

myscript.py set_modem_bank -bank ${num}  -modem ${modem_num} 

I would like it to work with either type of call, from CLI and from inside a python script.

Paul
  • 5,756
  • 6
  • 48
  • 78

2 Answers2

1

Your change_modem_bank function tries to access args directly, which works when you call it as a command-line script since it's in the module namespace then, but fails when you call it separately. Just fix it to get args passed in instead:

def change_modem_bank(bank_num, modem):  
    if "1" in bank_num:
        print "2" 
    elif "2" in bank_num:
         print "2"
    print modem

And call it with:

args.func(args.sim_bank, args.modem_num)

You'll have to figure out what your function is supposed to do if the arguments are None, since that will cause an error now.

tzaman
  • 46,925
  • 11
  • 90
  • 115
1

When you call it as a script, what happens is:

args=parser.parse_args()
change_modem_bank() # equivalent to args.func()

When you import the module, that main part is skipped, so args is not set. If you want to call change_modem_back as is, then you need to create an args variable that looks like the one that the parser would generate. Here's one way of doing that:

import cellular_modem
import argparse
args = argparse.Namepspace(simbank=xxx, modem_num=xxx)
cellular_modem.change_modem_bank("2","0")

Your function assumes that, in its global argument space there is an object with these 2 attributes:

args.sim_bank, args.modem_num

You change the function to something like:

def change_modem_bank(bank_num=None, modem=None, args=None):  
    if args and args.sim_bank and args.modem_num:
        bank_num = args.sim_bank
        modem = args.modem_num  

and invoke it in the main as:

args.func(args=args)

This way it is clear where the function is getting its args variable from. It also behaves rationally when args is a simple default value like None.

One way or other you need to initialize an args variable when importing, and then write your function is a way that it will be ok with that default version.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • Thanks great answer, unfortunately doens't work in my case as then all functions would need at least one argument from args=args and most of them don't have one. Will work it out! – Paul May 19 '15 at 09:07
  • solved it with a wrapper function, cheers for the help. – Paul May 19 '15 at 10:35