35

This is probably a silly question, but I have a python script that current takes in a bunch of arguments using argparser and I would like to load this script as a module in another python script, which is fine. But I am not sure how to call the module as no function is defined; can I still call it the same way I do if I was just invoking it from cmd?

Here is the child script:

import argparse as ap
from subprocess import Popen, PIPE

parser = ap.ArgumentParser(
    description='Gathers parameters.')
parser.add_argument('-f', metavar='--file', type=ap.FileType('r'), action='store', dest='file',
                    required=True, help='Path to json parameter file')
parser.add_argument('-t', metavar='--type', type=str, action='store', dest='type',
                    required=True, help='Type of parameter file.')
parser.add_argument('-g', metavar='--group', type=str, action='store', dest='group',
                    required=False, help='Group to apply parameters to')
# Gather the provided arguments as an array.
args = parser.parse_args()

... Do stuff in the script

and here is the parent script that I want to invoke the child script from; it also uses arg parser and does some other logic

from configuration import parameterscript as paramscript

# Can I do something like this?
paramscript('parameters/test.params.json', test)

Inside the configuration directory, I also created an init.py file that is empty.

3 Answers 3

42

The first argument to parse_args is a list of arguments. By default it's None which means use sys.argv. So you can arrange your script like this:

import argparse as ap

def main(raw_args=None):
    parser = ap.ArgumentParser(
        description='Gathers parameters.')
    parser.add_argument('-f', metavar='--file', type=ap.FileType('r'), action='store', dest='file',
                        required=True, help='Path to json parameter file')
    parser.add_argument('-t', metavar='--type', type=str, action='store', dest='type',
                        required=True, help='Type of parameter file.')
    parser.add_argument('-g', metavar='--group', type=str, action='store', dest='group',
                        required=False, help='Group to apply parameters to')
    # Gather the provided arguments as an array.
    args = parser.parse_args(raw_args)
    print(vars(args))


# Run with command line arguments precisely when called directly
# (rather than when imported)
if __name__ == '__main__':
    main()

And then elsewhere:

from first_module import main

main(['-f', '/etc/hosts', '-t', 'json'])

Output:

{'group': None, 'file': <_io.TextIOWrapper name='/etc/hosts' mode='r' encoding='UTF-8'>, 'type': 'json'}
Sign up to request clarification or add additional context in comments.

1 Comment

and to avoid needing to manually split argument lists: main('-f /etc/hosts -t json'.split()) or if splitting needs to be more sophisticated: import shlex; main(shlex.split('-f /etc/hosts -t json -g "special group name with spaces"')) (shlex is in the standard library.)
4

There may be a simpler and more pythonic way to do this, but here is one possibility using the subprocess module:

Example:

child_script.py

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-n", "--name", help="your name")
args = parser.parse_args()

print("hello there {}").format(args.name)

Then another Python script can call that script like so:

calling_script.py:

import subprocess

# using Popen may suit better here depending on how you want to deal
# with the output of the child_script.
subprocess.call(["python", "child_script.py", "-n", "Donny"])

Executing the above script would give the following output:

"hello there Donny"

2 Comments

Speaking from experience here, using subprocess to run python instead of importing modules leads to issues down the line. A FileNotFoundException in your subprocess turns into a return code that you have to check and handle with more than you would otherwise have to without subprocess. "except FileNotFoundError: raise" turns into spaghetti with subprocess. This is the tip of the iceberg. For the sake of your future self and coworkers, don't do this.
Subprocesses cost significant overhead.
2

One of the option is to call it as subprocess call like below:

import subprocess
childproc = subprocess.Popen('python childscript.py -file yourjsonfile')
op, oe = childproc.communicate()
print op

1 Comment

Subprocesses are expensive.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.