问题 django如何将字符串转换为模块


我试图理解关于django的另一个神奇之处:它可以将字符串转换为模块。

在settings.py中,INSTALLED_APPS声明如下:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
)

它包含的只是字符串。但是django会将这些字符串转换为模块并在以后导入它们。

我希望能够做同样的事情。但我不知道怎么做。 我在settings.py中有一个渲染器调度程序的字典:

RESOUCE_RENDERER = {
    'video': 'video_player',
    'audio': 'audio_player', 
}

我想稍后使用它: RESOURCE_RENDERER['video'](MyVideo)

我无法直接分配函数名称(例如video_player),因为它位于需要settings.py的模块中。


9152
2017-09-09 01:45


起源



答案:


从Django 1.7开始 一个简单的功能。例如:

from django.utils.module_loading import import_string
my_module = import_string('path.to.my_module')

您还可以从模块中获取课程:

MyClass = import_string('path.to.my_module.MyClass')

8
2017-11-10 10:15





看看吧 django.conf.__init__.py,但基本上它使用 导入库 像这样:

try:
    mod = importlib.import_module(self.SETTINGS_MODULE)
except ImportError, e:
    raise ImportError("Could not import settings '%s' 
               (Is it on sys.path? Does it have syntax errors?):
                %s" % (self.SETTINGS_MODULE, e))

# Settings that should be converted into tuples if they're mistakenly entered
# as strings.
tuple_settings = ("INSTALLED_APPS", "TEMPLATE_DIRS")

编辑:根据OP的要求,我扩展了这个例子并在下面做了一些贡献。

现在,假设您在此模块中有一个函数列表,例如在函数列表中定义的函数列表。然后,你可以像这样打电话给每个人:

ARGUMENTS = '()'

for FUNCTION in FUNCTIONS_TO_CALL:
    function_string = FUNCTION + ARGUMENTS
    exec(function_string)

这假设每个函数都具有相同的已定义参数集。您可以使用if语句来检测用户列出的函数名称,并根据具体情况提供自定义参数。您还可以通过读取python文件来评估参数应该是什么。

您还可以检查模块对象(我认为这是可能的,我不知道)在调用之前查看该函数是否存在 exec() 要么 eval()。我不知道,如果可以从函数对象中评估它需要什么参数。我怀疑是这样,但这是一个单独的(可能已经回答?)问题。


8
2017-09-09 01:49



@Ninefingers,这会有所帮助,但我希望导入函数,而不仅仅是模块。你知道我怎么能做到吗? - maroxe
我猜 进口 是我在找什么 - maroxe
是的,不是。 import语句是importlib函数的回绕,因此,当你有趣的import_module时 有 导入了一个变量模块 仿佛 你要求“导入一些变量”。我认为你不能 import 变量名,但你可以通过这个库。现在,一旦您导入了一个模块,您就可以访问其中的所有内容 - 我将上面的示例扩展为包含代码访问 INSTALLED_APPS 从设置文件中,如q中所述。
@Ninefingers i meaned import包含两个下划线(解析器将其粗体化)。我不能从字符串中调用函数,只是一个字符串。我不明白你的新例子(我猜你已经忘记了一些线条) - maroxe
我应该添加这个在.net / java中称为Reflection。


答案:


从Django 1.7开始 一个简单的功能。例如:

from django.utils.module_loading import import_string
my_module = import_string('path.to.my_module')

您还可以从模块中获取课程:

MyClass = import_string('path.to.my_module.MyClass')

8
2017-11-10 10:15





看看吧 django.conf.__init__.py,但基本上它使用 导入库 像这样:

try:
    mod = importlib.import_module(self.SETTINGS_MODULE)
except ImportError, e:
    raise ImportError("Could not import settings '%s' 
               (Is it on sys.path? Does it have syntax errors?):
                %s" % (self.SETTINGS_MODULE, e))

# Settings that should be converted into tuples if they're mistakenly entered
# as strings.
tuple_settings = ("INSTALLED_APPS", "TEMPLATE_DIRS")

编辑:根据OP的要求,我扩展了这个例子并在下面做了一些贡献。

现在,假设您在此模块中有一个函数列表,例如在函数列表中定义的函数列表。然后,你可以像这样打电话给每个人:

ARGUMENTS = '()'

for FUNCTION in FUNCTIONS_TO_CALL:
    function_string = FUNCTION + ARGUMENTS
    exec(function_string)

这假设每个函数都具有相同的已定义参数集。您可以使用if语句来检测用户列出的函数名称,并根据具体情况提供自定义参数。您还可以通过读取python文件来评估参数应该是什么。

您还可以检查模块对象(我认为这是可能的,我不知道)在调用之前查看该函数是否存在 exec() 要么 eval()。我不知道,如果可以从函数对象中评估它需要什么参数。我怀疑是这样,但这是一个单独的(可能已经回答?)问题。


8
2017-09-09 01:49



@Ninefingers,这会有所帮助,但我希望导入函数,而不仅仅是模块。你知道我怎么能做到吗? - maroxe
我猜 进口 是我在找什么 - maroxe
是的,不是。 import语句是importlib函数的回绕,因此,当你有趣的import_module时 有 导入了一个变量模块 仿佛 你要求“导入一些变量”。我认为你不能 import 变量名,但你可以通过这个库。现在,一旦您导入了一个模块,您就可以访问其中的所有内容 - 我将上面的示例扩展为包含代码访问 INSTALLED_APPS 从设置文件中,如q中所述。
@Ninefingers i meaned import包含两个下划线(解析器将其粗体化)。我不能从字符串中调用函数,只是一个字符串。我不明白你的新例子(我猜你已经忘记了一些线条) - maroxe
我应该添加这个在.net / java中称为Reflection。