如何使Python程序能够加载和使用几个同名的不同包?

2024-10-03 21:24:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在开发一个控制硬件的Python应用程序。硬件由基于FPGA的系统组成。从控制的角度来看,它们的内部结构由自动化系统AGWB(http://github.com/wzab/agwb.git)管理

每个系统的描述被编译成一个Python模块“agwb”,其中包含几个子模块。 加载模块后,它用于生成一个对象,处理与相关系统的进一步通信

当我的应用程序与几个不同的系统一起工作时,它必须加载几个不同的“agwb”模块(当然,每个模块都来自不同的目录)

通过在sys.path的开头添加该目录(并在加载模块后将其删除),可以轻松地从指定目录加载模块

不幸的是,Python只导入模块“agwb”一次。以后尝试导入它会导致使用以前加载的。 使用importlib.reload也没有帮助。 在阅读了https://docs.python.org/3/reference/import.html之后,我找到了以下解决方案:

import sys
import importlib

def load_agwb(lddir,top):
    sys.path.insert(0,lddir)
    importlib.import_module('agwb')
    # Get the class for the top entity
    res = getattr(sys.modules['agwb'],top)()
    sys.path.remove(lddir)
    sys.modules.pop('agwb')
    mods_to_remove = []
    for mod in sys.modules.keys():
        if mod.find('agwb.') == 0:
            mods_to_remove.append(mod)
    for mod in mods_to_remove:
        sys.modules.pop(mod)
    return res

at1 = load_agwb('./t1','top_v0')
at2 = load_agwb('./t2','top_v0')
print("Call at1.show")
at1.show()
print("Call at2.show")
at2.show()

目录“/t1”和“/t2”包含两个不同版本的“agwb”模块

执行脚本后,我们得到以下输出,证明确实加载了“agwb”的两个不同版本并同时使用:

Call at1.show
object from t1, desc= That's version from directory t1
type ID= 1111
Call at2.show
object from t2, desc= That's version from directory t2
type ID= 2222

整个最小演示器(作为shar存档)可以在https://pastebin.com/ZGZj8qV1上找到(不幸的是,我无法将文件附加到我的问题)

下面是我的问题:

  • 上述方法在Python中是可靠的合法解决方案吗
  • 也许它只是偶然工作,可能会在下一个版本的Python中停止工作
  • 还有其他更“正式”的方法来解决我的问题吗

Tags: 模块import目录modulesmodtop系统show
1条回答
网友
1楼 · 发布于 2024-10-03 21:24:52

我已经根据pavel's的评论创建了一个答案(非常感谢!)。 我使用了临时目录和符号链接来解决长而复杂的路径问题。结果如下:

import sys
import os
import importlib
import tempfile

# Directory with description of the first board
dir1 = './xt1/very/long/path'
# Directory with description of the second board
dir2 = './xt2/completely/different/path'

# Name of the top entity in the design
top = 'top_v0'

# Create a temporary directory
tmpdir = tempfile.TemporaryDirectory()

# Add it to the Python path
sys.path.insert(0,tmpdir.name)

# Create symlinks to the directories with descriptions of the boards
os.symlink(os.path.abspath(dir1),tmpdir.name+"/t1")
os.symlink(os.path.abspath(dir2),tmpdir.name+"/t2")

# Import description of the first board as agwb
import t1.agwb as agwb

# use the imported agwb
at1 = getattr(agwb,top)()
# if the name of the top entity is constant, you can do it easier
bt1 = agwb.top_v0()

# Import description of the second board as agwb
import t2.agwb as agwb

# use the imported agwb
at2 = getattr(agwb,top)()
# if the name of the top entity is constant, you can do it easier
bt2 = agwb.top_v0()

# Now we can remove the temporary directory from the python path
sys.path.remove(tmpdir.name)
# We can even delete it (otherwise it will be deleted when Python session ends)
tmpdir.cleanup()

# Check if both versions are loaded and available
print("Call at1.show")
at1.show()
print("Call at2.show")
at2.show()

print("Call bt1.show")
bt1.show()
print("Call bt2.show")
bt2.show()

如前所述,整个minimal reproducerhttps://pastebin.com/GrRUh8U9以shar格式提供

相关问题 更多 >