0

After trying the solution offered by this thread: What is the best way to call a Python script from another Python script?

I came along with another problem dealing with arguments.

I have:

test1.py

def some_func():
    print 'in test 1, unproductive'

if __name__ == '__main__':
    # test1.py executed as script
    # do something
    some_func()

service.py (with dummy arguments)

import argparse
import test1

actions = ['start', 'remove']
parser = argparse.ArgumentParser()
parser.add_argument("action", help="Possible actions are: "
    "'{d[0]}|{d[1]}' ".format(d=actions))
parser.add_argument("-d", "--debug", help="Debug mode", action="store_true")
args = parser.parse_args()

def service_func():
    print 'service func'

if __name__ == '__main__':
    # service.py executed as script
    # do something
    service_func()
    test1.some_func()

This works:

python service.py start
service func
in test 1, unproductive

However, if I want to add arguments in test1.py as well:

test1.py

import argparse

######## new stuff  ##########
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--debug", help="Debug mode", action="store_true")
args = parser.parse_args()
##############################

def some_func():
    print 'in test 1, unproductive'

if __name__ == '__main__':
    # test1.py executed as script
    # do something
    some_func()

Now I get:

python service.py start
usage: service.py [-h] [-d]
service.py: error: unrecognized arguments: start

Not sure why...

Community
  • 1
  • 1
hosselausso
  • 967
  • 1
  • 10
  • 28

1 Answers1

0

python service.py start - to argparse 'start' looks like a positional argument. It does not have a '--' to mark it as a flag string.

I'm guessing the parser in service.py is handling it ok, though you don't display or otherwise use the resulting args.

The usage in the error message is consistent with the parser in test1.py. It does not define a positional, just the --debug

usage: service.py [-h] [-d]

test1.py is using the same sys.argv list.

There are several solutions:

  • add a positional argument to test1

  • use parse_known_args instead of parse_args.

  • modify sys.argv in service.py (after parsing) to remove this 'start' string. A change in sys.argv in this script will carry over to test1. Print sys.argv in both to be sure.

  • use REMAINDER as documented in the docs

argparse.REMAINDER. All the remaining command-line arguments are gathered into a list. This is commonly useful for command line utilities that dispatch to other command line utilities:


Call

args, extras = parser.parse_known_args()

This would set

args to Namespace(debug=False) and extras to ['start']. Otherwise you get a tuple of these two values, (Namespace(debug=False), ['start']).

If you haven't modified sys.argv in the first script, the 2nd one will see the same list. Parsing does not modify this list.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • Oh, using `parse_known_args` instead of `parse_args` made it work. Thanks! I was trying the solution with REMAINDER but I'm not sure how/where to use it.. – hosselausso Apr 25 '16 at 20:53
  • However, when printing the args variable for both scripts.. there is a problem: test1.args: (Namespace(debug=False), ['start']) services.args: Namespace(action='start', debug=False) so the argument "start" is passed to test1.py somehow... – hosselausso Apr 26 '16 at 07:58