I'm writing a small utility function which takes in input arguments of the location of a Python file, and also a function to call within the Python file
For example src/path/to/file_a.py
def foo():
...
In the utility function, I'm parsing the arguments like so:
python ./util.py --path src/path/to/file_a.py --function foo
and the foo
function needs to be used later in the util.py
in another library:
def compile():
compiler.compile(
function=foo,
etc
)
What's the best way of importing the foo
function via argparse?
Some initial thoughts:
util.py
:
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument("--path", type=str)
parser.add_argument("--function", type=str)
return parser.parse_args()
def compile(path, function):
import path
compiler.compile(
function=path.function,
etc
)
if __name__ == "__main__":
args = get_args()
compile(
path=args.path
function=args.function
)
however importing via argparse, and adding it to the function does not seem to work nicely.
There's also the idea of using sys.path.append
:
def compile(path, function):
import sys
sys.path.append(path)
but then I'm unsure of how to import the foo
function from that.
CodePudding user response:
This problem can be rephrased as "how do I import a python file given a path?" To do that, we can use https://stackoverflow.com/a/67692/5666087. Here is a code example that incorporates the answer to that question with your needs.
import argparse
import importlib.util
import sys
def get_function_object(path_to_pyfile: str, funcname: str):
spec = importlib.util.spec_from_file_location("tmpmodulename", path_to_pyfile)
module = importlib.util.module_from_spec(spec)
sys.modules["tmpmodulename"] = module
spec.loader.exec_module(module)
if not hasattr(module, funcname):
raise AttributeError(f"Cannot find function '{funcname}'in imported module")
# TODO: Consider testing whether this object is a callable.
return getattr(module, funcname)
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument("--path", type=str)
parser.add_argument("--function", type=str)
return parser.parse_args()
if __name__ == "__main__":
args = get_args()
function = get_function_object(args.path, funcname=args.function)
compiler.compile(function=funtion)