我正在使用我的 pythonizer 工具自动将一些 perl 代码转换为 python。 perl 代码使用 Date::Manip 包,它有一个子模块 Date::Manip::Date。我在生成的代码中使用
Date
变量(我在 builtins
中定义)来保存我定义 Date.Manip
的名称空间。当我导入 Date.Manip.Date 包时,即使我将其作为 _Date_Manip_Date
导入,导入仍然会设置一个全局 Date
变量以防止访问我的 Date
命名空间。我正在寻找有关如何避免此问题的想法。我无法更改子模块的名称。这是重现问题的代码(注意我在这个测试用例中使用 Date
作为字符串而不是名称空间):
# date_issue.py:
import sys
sys.path[0:0] = '.'
import Date.Manip as _Date_Manip
# Date/Manip/__init__.py:
Date = '2023-04-15'
import Date.Manip.Date as _Date_Manip_Date
assert Date == '2023-04-15', f"Date got changed to {Date}"
# Date/Manip/Date.py (empty file)
我在断言上得到这个错误:
AssertionError: Date got changed to <module 'Date.Manip.Date' from '/mnt/c/pythonizer/play/./Date/Manip/Date.py'>
我正在考虑在导入之前保存
Date
的值并在之后恢复它,并且只有在导入的模块名称与任何父命名空间同名时才这样做,但是你有有更好的主意吗?
你知道如果你做类似的事情怎么办
import collections.abc
你现在可以写
collections.abc
并下定决心做正确的事了吗?这是 collections
包的模块对象的属性访问。为此,子模块必须作为该对象的 abc
属性可用。
为了让它工作,加载包子模块将该子模块设置为父包的属性。因为模块只在第一次导入时加载,所以这个属性分配发生在第一次导入子模块时,无论导入是什么样子 - 导入中的
as
不会改变这个。
试图搞砸这个是个坏主意。如果属性访问链
Date.Manip.Date
解析为 Date.Manip.Date
模块以外的其他内容,则各种奇怪的东西都会中断。不幸的是,您正在尝试自动翻译用不同语言编写的库,因此您没有选择以不同方式设计库的选项。这只是导致此类自动翻译尝试大多注定失败的众多不兼容性之一。