简体   繁体   English

动态导入 Python 模块

[英]Dynamically importing Python module

I have a trusted remote server that stores many custom Python modules.我有一个受信任的远程服务器,可以存储许多自定义 Python 模块。 I can fetch them via HTTP (eg using urllib2.urlopen ) as text/plain, but I cannot save the fetched module code to the local hard disk.我可以通过 HTTP(例如使用urllib2.urlopen )作为文本/纯文本获取它们,但我无法将获取的模块代码保存到本地硬盘。 How can I import the code as a fully operable Python module, including its global variables and imports?如何将代码作为完全可操作的 Python 模块导入,包括其全局变量和导入?
I suppose I have to use some combination of exec and imp module's functions, but I've been unable to make it work yet.我想我必须使用execimp模块函数的某种组合,但我还无法使其工作。

It looks like this should do the trick: importing a dynamically generated module看起来这应该可以解决问题: 导入动态生成的模块

>>> import imp
>>> foo = imp.new_module("foo")
>>> foo_code = """
... class Foo:
...     pass
... """
>>> exec foo_code in foo.__dict__
>>> foo.Foo.__module__
'foo'
>>>

Also, as suggested in the ActiveState article, you might want to add your new module to sys.modules :此外,正如 ActiveState 文章中所建议的,您可能希望将新模块添加到sys.modules

>>> import sys
>>> sys.modules["foo"] = foo
>>> from foo import Foo
<class 'Foo' …>
>>>

Here's something I bookmarked a while back that covers something similar:这是我不久前添加的书签,其中涵盖了类似的内容:

It's a bit beyond what you want, but the basic idea is there.这有点超出您的要求,但基本思想就在那里。

Python3 version Python3版本
(attempted to edit other answer but the edit que is full) (试图编辑其他答案,但编辑 que 已满)

import imp

my_dynamic_module = imp.new_module("my_dynamic_module")
exec("""
class Foo:
    pass
""", my_dynamic_module.__dict__)

Foo = my_dynamic_module.Foo
foo_object = Foo()

# register it on sys
import sys
sys.modules[my_dynamic_module.__name__] = my_dynamic_module

I recently encountered trying to do this while trying to write unit tests for source code examples I put into a project's readme (I wanted to avoid just linking to small files or duplicating the text in a way that could get out of sync).我最近在尝试为我放入项目自述文件的源代码示例编写单元测试时遇到了这种情况(我想避免仅链接到小文件或以可能不同步的方式复制文本)。

I came up with the following我想出了以下内容

import sys
import types
from importlib import import_module


def compile_and_install_module(module_name: str, source_code: str) -> types.ModuleType:
    """Compile source code and install it as a module.

    End result is that `import <module_name>` and `from <module_name> import ...` should work.
    """
    module = types.ModuleType(module_name, "Module created from source code")

    # Execute source in context of empty/fake module
    exec(source_code, module.__dict__)

    # Insert fake module into sys.modules. It's now a real module
    sys.modules[module_name] = module

    # Imports should work now
    return import_module(module_name)

And a quick example of how you can use it以及如何使用它的快速示例

$ cat hello.py 
def foo():
    print("Hello world")


bar = 42

$ python
Python 3.9.5 (tags/v3.9.5:0a7dcbd, May  3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from compile import compile_and_install_module
>>> compile_and_install_module("hello", open("hello.py").read())
<module 'hello'>
>>> import hello
>>> hello.foo()
Hello world
>>> from hello import bar
>>> bar
42

You can remove the return value and import_lib import if you您可以删除返回值和 import_lib 导入,如果您

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

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