如何在Python中以编程方式调用函数也以编程方式指定模块?

时间:2018-12-12 14:23:23

标签: python package

我不能使用这个

import foo
method_to_call = getattr(foo, 'bar')
result = method_to_call()

因为模块名称是硬编码的,所以我不能使用它

module = __import__('foo')
func = getattr(module, 'bar')
func()

因为模块是嵌套的。

我尝试过

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()    

,但失败,并带有注释和每个变体中指定的错误。

get_gt()gt.py目录内customer/jci文件内的函数。每个目录内部都有空的__init__.py

以下硬编码代码有效:

import customer.jci.gt as g
gt = g.get_gt()

如何克服?

1 个答案:

答案 0 :(得分:3)

您想要的是importlib.import_module


请注意,__import__ 可以处理点名,但它会返回 parent 包,而不是最后一个子包。

证明:

>>> 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返回子模块,这是大多数人期望的:

>>> importlib.import_module('http.client')
<module 'http.client' from '/usr/lib/python3.6/http/client.py'>