Home > Software design >  Python import function from another file via argparse
Python import function from another file via argparse

Time:01-25

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)
  • Related