简体   繁体   English

在Python中从外部函数导入动态模块(或-在模块外部编辑globals())

[英]Dynamic module imports from external function, (or - editing globals() outside of module), in Python

I have a project in which I want to repeatedly change code in a class and then run other modules to test the changes (verification..). 我有一个项目,我想在其中重复更改类中的代码,然后运行其他模块以测试更改(验证..)。 Currently, after each edit I have to reload the code, the testing modules which run it, and then run the test. 当前,每次编辑后,我必须重新加载代码,运行该代码的测试模块,然后运行测试。 I want to reduce this cycle to one line, moreover, I will later want to test different classes, so I want to be able to receive the name of the tested class as a parameter - meaning I need dynamic imports. 我想将这一周期减少到一行,而且,稍后我将要测试不同的类,因此我希望能够接收被测试类的名称作为参数-这意味着我需要动态导入。

I wrote a function for clean imports of any module, it seems to work: 我编写了一个用于干净导入任何模块的函数,它似乎可以正常工作:

def build_module_clean(module_string,attr_strings):
    module = import_module(module_string)
    module = reload(module)
    for f in attr_strings:
        globals()[f]=getattr(module,f)

Now, in the name of cleanliness, I want to keep this function in a wrapper module (which will contain the one-liner I want to rebuild and test all the code each time), and run it from the various modules, ie among the import statements of my ModelChecker module I would place the line 现在,以清洁度为名,我希望将此功能保留在包装模块中(该包装模块将包含我想重新构建并测试所有代码的单行代码),并从各个模块(即在我将输入ModelChecker模块的语句

from wrapper import build_module_clean
build_module_clean('test_class_module',['test_class_name'])

however, when I do this, it seems the test class is added to the globals in the wrapper module, but not in the ModelChecker module (attempting to access globals()['test_class_name'] in ModelChecker gives a key error). 然而,当我做到这一点,似乎在测试类添加到封装模块中的全局变量,而不是在ModelChecker模块(试图访问globals()['test_class_name']ModelChecker给出了一个关键的错误)。 I have tried passing globals or globals() as further parameters to build_module_clean , but globals is a function (so the test module is still loaded to the wrapper globals ), and passing and then using globals() gives the error 我尝试过将globalsglobals()作为进一步的参数传递给build_module_clean ,但是globals是一个函数(因此测试模块仍会加载到wrapper globals ),然后传递并使用globals()会给出错误

TypeError: 'builtin_function_or_method' object does not support item assignment

So I need some way to edit one module's globals() from another module. 因此,我需要某种方法来从另一个模块编辑一个模块的globals()


Alternatively, (ideally?) I would like to import the test_class module in the wrapper, in a manner that would make it visible to all the modules that use it (eg ModelChecker ). 或者,(理想情况下?)我想以一种使所有使用它的模块(例如ModelChecker )可见的方式在包装器中导入test_class模块。 How can I do that? 我怎样才能做到这一点?

Your function should look like: 您的函数应如下所示:

def build_module_clean(globals, module_string, attr_strings):
    module = import_module(module_string)
    module = reload(module)
    globals[module_string] = module
    for f in attr_strings:
        globals[f] = getattr(module, f)

and call it like so: 并这样称呼它:

build_module_clean(globals(), 'test_class_module', ['test_class_name'])

Explanation: 说明:

Calling globals() in the function call ( build_module_clean(globals()... ) grabs the module's __dict__ while still in the correct module and passes that to your function. 在函数调用( build_module_clean(globals()... )中调用globals()在仍处于正确模块中的同时获取模块的__dict__并将其传递给函数。

The function is then able to (re)assign the names to the newly-loaded module and it's current attributes. 然后,该函数可以将名称(重新)分配给新加载的模块及其当前属性。

Note that I also (re)assigned the newly-loaded module itself to the globals (you may not want that part). 请注意,我也将新加载的模块本身(重新)分配给了全局变量(您可能不需要该部分)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM