簡體   English   中英

動態導入 Python 模塊

[英]Dynamically importing Python module

我有一個受信任的遠程服務器,可以存儲許多自定義 Python 模塊。 我可以通過 HTTP(例如使用urllib2.urlopen )作為文本/純文本獲取它們,但我無法將獲取的模塊代碼保存到本地硬盤。 如何將代碼作為完全可操作的 Python 模塊導入,包括其全局變量和導入?
我想我必須使用execimp模塊函數的某種組合,但我還無法使其工作。

看起來這應該可以解決問題: 導入動態生成的模塊

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

此外,正如 ActiveState 文章中所建議的,您可能希望將新模塊添加到sys.modules

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

這是我不久前添加的書簽,其中涵蓋了類似的內容:

這有點超出您的要求,但基本思想就在那里。

Python3版本
(試圖編輯其他答案,但編輯 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

我最近在嘗試為我放入項目自述文件的源代碼示例編寫單元測試時遇到了這種情況(我想避免僅鏈接到小文件或以可能不同步的方式復制文本)。

我想出了以下內容

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)

以及如何使用它的快速示例

$ 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

您可以刪除返回值和 import_lib 導入,如果您

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM