pythonmodulepython-importoptionparser

Is it possible to send an 'OptionParser' object as input arguement to run main of imported python module?


There are two python scripts, 'script1.py' and 'script2.py'.

'script1.py' uses OptionParser to parse command line arguments.

The contents of 'script1.py' look something like this

from optparse import OptionParser

def main():
    parser = OptionParser()
    parser.add_option("-o", "--option1")
    parser.add_option("-p", "--option2")
    (opts, args) = parser.parse_args()

    # Do things with the options

if __name__ == '__main__':
    main()

To run it on a command line. It is run with:

python script1.py -o Option1 -p Option2

'script2.py' also uses OptionParser implemented in the same way but with a different set of options.

'script2.py' also has 'script1.py' imported as a module.

I would like to run the main of script1.py from script2.py. What is the best way to do this?

One way I got this to work is by changing the main of script1.py to take OptionParser as an arguement.

def main(OptionParser):
...
...
...
if __name__ == '__main__':
    main(OptionParser)

And making sure the OptionParser for both the scripts have exactly the same options. If I do that then I can just pass the OptionParser object from script2 into script1 as follows:

script1.main(OptionParser)

Is there a way to achieve the same result without making the OptionParser in both the scripts the same.

Ideally, I would like it to work as follows:

script1.main(option1="Option1", option2="Option2")

This way I can run script1 from the command line as well as from another script.

Edit: I'm also aware I can used subprocess and os.system() to execute the python script. I'm wondering if there are neater ways to design the interaction between the two scripts.

Edit 2: As per Mig's suggestion I moved the option parser out of main.

scrip1.py looks as follows now

def main(option1, option2):
    # Do main things

if __name__ == '__main__':
    parser = OptionParser()
    parser.add_option("-o", "--option1")
    parser.add_option("-p", "--option2")
    (opts, args) = parser.parse_args()

    main(option1=opts.option1, option2=opts.option2)

Now from script2.py after importing script1.py as a module I can call main of script1 script1.main(option1="Option1", option2="Option2").


Solution

  • If you have functions that are supposed to work both as main script and as imported, then I would not use opt parser in it. There are many ways to do this but you can have a main that only takes care of your opt parser and then passing right arguments to the function which is really responsible for the job. Do you see what I mean?

    Then in this case calling it from the command line will take the arguments from an opt parser, but if you use it as a library, then you call the function doing the job instead.

    Another way to do this is which is pretty similar is to keep main as the function doing the real job, but you create the opt parser in the if __name__ == '__main__': block at the end. You build your opt parser in the this block and call main with the arguments it needs.

    All in all the principle is to separate the real job from the option parsing.

    I don't know all the details of your application, so it may not be the answer you are looking for, but it is quite a common thing to do in many programming languages.