'pass command-line arguments to runpy

I have two files, one which has a side effect I care about that occurs within the if __name__ == "__main__" guard:

# a.py
d = {}
if __name__ == "__main__":
    d['arg'] = 'hello'

The second file imports the first (using runpy) and prints the dictionary:

# b.py
import runpy
m = runpy.run_module('a', run_name='__main__')
print(m['d'])  # {'arg': 'hello'}

So far this works. But now I want to change the first file to accept a command line argument:

import sys
d = {}
if __name__ == "__main__":
    d['arg'] = process(sys.argv[1])

The problem is that process() is written by someone else and outside of my control, but I still want to get the updated dictionary d after it has been "processed".

How can I mock sys.argv before calling runpy, or otherwise provide that value to a.py?



Solution 1:[1]

For those who stumbled across this post like me, you can just pass the command line arguments directly. As an example, if I have

# a.py
import argparse

def parse_args():
    # fmt: off
    parser = argparse.ArgumentParser()
    parser.add_argument("--myvar")
    args = parser.parse_args()
    # fmt: on
    return args

if __name__ == "__main__":
    args = parse_args()
    print(args.myvar)
# b.py

import runpy
runpy.run_path(path_name='a.py', run_name="__main__")

I get

$ python a.py 
None
$ python a.py --myvar test
test
$ python b.py 
None
$ python b.py --myvar test
test

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Costa Huang