How to call functions programmatically and specify modules programmatically in Python?… here is a solution to the problem.
How to call functions programmatically and specify modules programmatically in Python?
I can’t use this
import foo
method_to_call = getattr(foo, 'bar')
result = method_to_call()
Because the module name is hardcoded, I can’t use it
module = __import__('foo')
func = getattr(module, 'bar')
func()
Because modules are nested.
I tried
customer = 'jci'
module = __import__('customer.{ customer_name}.gt'.format(customer_name=customer_name)) # AttributeError: module 'customer' has no attribute 'get_gt'
#module = __import__('customer.{ customer_name}'.format(customer_name=customer_name), fromlist=['gt']) # AttributeError: module 'customer.jci' has no attribute 'get_gt'
#module = __import__('customer.{ customer_name}.gt'.format(customer_name=customer_name), fromlist=[]) # AttributeError: module 'customer' has no attribute 'get_gt'
func = getattr(module, 'get_gt')
gt = func()
But failed due to an error, specified in the comment with each variant.
get_gt()
is a function in the gt.py
file in the customer/jci
directory. Each directory has an empty __init__.py
.
The following hard-coded code works:
import customer.jci.gt as g
gt = g.get_gt()
How to overcome?
Solution
What you want is > importlib.import_module .
Note that __import__
does handle the name of the dot, but it returns the parent package, not the last child package.
Proof:
>>> http = __import__('http.client')
>>> http.client # the client submodule was imported
<module 'http.client' from '/usr/lib/python3.6/http/client.py'>
>>> # without specifying the .client in the name the submodule is not imported
>>> __import__('http').client
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'http' has no attribute 'client'
import_module
instead of returning a submodule, which is what most people expect :
>>> importlib.import_module('http.client')
<module 'http.client' from '/usr/lib/python3.6/http/client.py'>