0

If I import a Python module that is already using argparse, however, I would like to use argparse in my script as well ...how should I go about doing this?

I'm receiving a unrecognized arguments error when using the following code and invoking the script with a -t flag:

Snippet:

#!/usr/bin/env python

....
import conflicting_module
import argparse
...

#################################
# Step 0: Configure settings... #
#################################
parser = argparse.ArgumentParser(description='Process command line options.')
parser.add_argument('--test', '-t')

Error:

 unrecognized arguments: -t foobar
Paul Calabro
  • 1,748
  • 1
  • 16
  • 33
  • 2
    Please show the full code and the full command line arguments you are passing to your script. You may find this to be useful: [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) – Andrea Corbellini Mar 15 '16 at 10:05

1 Answers1

4

You need to guard your imported modules with

if __name__ == '__main__':
    ...

against it running initialization code such as argument parsing on import. See What does if __name__ == "__main__": do?.

So, in your conflicting_module do

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Process command line options in conflicting_module.py.')
    parser.add_argument('--conflicting', '-c')
    ...

instead of just creating the parser globally.

If the parsing in conflicting_module is a mandatory part of application configuration, consider using

args, rest = parser.parse_known_args()

in your main module and passing rest to conflicting_module, where you'd pass either None or rest to parse_args:

args = parser.parse_args(rest)

That is still a bit bad style and actually the classes and functions in conflicting_module would ideally receive parsed configuration arguments from your main module, which would be responsible for parsing them.

Community
  • 1
  • 1
Ilja Everilä
  • 50,538
  • 7
  • 126
  • 127
  • It looks like most the code is contained within the constructor. Even if I move line 39 into the constructor, it still produces the same effect. https://github.com/paulcalabro/api-kickstart/blob/master/examples/python/config.py – Paul Calabro Mar 15 '16 at 10:16
  • I'm guessing you use `EdgeGridConfig` then. It will still add those arguments, and on line https://github.com/paulcalabro/api-kickstart/blob/master/examples/python/config.py#L60 attempt to parse them and fail. – Ilja Everilä Mar 15 '16 at 10:19
  • @PaulCalabro to put it in other words: you're out of luck with this one. – Ilja Everilä Mar 15 '16 at 10:20
  • Okay, I can workaround that. Just wanted to know if there was a Pythonic way to handle this kindof thing. Thanks! – Paul Calabro Mar 15 '16 at 10:23
  • 1
    @PaulCalabro Remove the argument parsing from `__init__`, make it a separate method to be called. Call it in your module guarded with the `if __name__ == '__main__':`, if you must. Allow the method to receive [unknown arguments](https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.parse_known_args) – Ilja Everilä Mar 15 '16 at 10:25
  • Good idea! I'll give that a try and post back. Ty! – Paul Calabro Mar 15 '16 at 10:27
  • As per https://stackoverflow.com/a/47587545/5472444, simply using `args = parser.parse_args(args=[])` worked for me when dealing with the error `ipykernel_launcher.py: error: unrecognized arguments: -f` caused by the way ipython jupyter extension in vscode was running. Since the module with conflict was a 'silent' dependency I wasn't importing, it wasn't clear to me how I'd pass on `rest` as per the solution above. – JPvRiel Jul 05 '19 at 16:32