【发布时间】:2018-10-15 17:39:20
【问题描述】:
我有同一个 Python 包的两个版本。我需要从当前版本的子包中的模块中调用旧版本包中的函数(过去复制了自己)
我现在在哪里:
now/
package/
__init__.py
subpackage/
__init__.py
module.py -> "import package.subpackage.... <HERE>"
subpackage2/
...
...
旧版本:
past/
package/
__init__.py
subpackage/
__init__.py
module.py -> "import package.subpackage; from . import module2; .... def f(x) ..."
module2.py
subpackage2/
...
...
我需要在<HERE> 中导入“旧”f 并运行它。
理想情况下
- 函数
f应该在旧包中生存,而不需要对包的新版本一无所知 - 新包中的模块应该调用它,让它活下去,得到结果然后完全忘记旧包的存在(所以在让
f做她的事情之后调用“import package.subpackage2”应该运行“新”版本) - 这样做不应该非常复杂
其基本思想是通过将我用于某些任务的代码与输出数据一起保存,然后能够运行其中的一部分来提高可重复性。
遗憾的是,我知道这不是 Python 3 的一项简单任务,因此我准备接受某种妥协。我准备接受,例如在运行旧的f(x) 后,“新”代码中的名称package 将绑定到旧代码。
编辑
我使用importlib 尝试了两种方式。想法是创建一个对象mod,然后做f = getattr(mod, "f"),但它不起作用
- 将
sys.path更改为['.../past/package/subpackage'],然后调用importlib.import_module('package.subpackage.module')。问题是即使更改了sys.path,它也会在“现在”中加载一个,可能是因为名称package已经在sys.modules中 -
spec = importlib.util.spec_from_file_location("module", "path..to..past..module.py")) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module)在这种情况下,相对导入 (from . import module2.py) 将不起作用,并给出错误“尝试了没有已知父包的相对导入”
【问题讨论】:
-
通常不建议这样做,因为旧版本的包通常与其他包和它们正在运行的 python 版本相互依赖。我建议使用酸洗参数之类的方法,在不同的
virtualenv中启动一个新的解释器,然后在其中解开并运行 -
在这种情况下,为什么常规导入不适合您?我认为没有任何防弹方法可以做到这一点,并保证两个版本的包之间不会有导入命名空间冲突。我不知道有任何库被设计为与同一库的其他版本共存。
-
我不明白:您是否要同时使用两个版本的
module.py?我假设def x(x):函数定义是它。 -
这是一个坏主意 ™。您不应同时使用同一个库的多个版本。
-
@HåkenLid 因为如果我已经在新目录中完成了
import package.subpackage2,即使我更改了sys.path,它也不会从旧目录导入package.subpackage.module。我相信它连接到包含'package'的sys.modules
标签: python python-3.x python-import binary-reproducibility