首页 > 解决方案 > Python 3:当本地模块存在同名时导入核心模块?

问题描述

我正在开发一个 Python 3 项目,不幸的是它有一个名为 的本地模块typing,它与内置typing模块发生冲突。

这样做的最终结果是我无法导入内置typing模块,因为首先引用本地typing模块并typingsys.modules.

我知道我可以将本地模块重命名为其他内容并修复所有引用,如果没有其他选择,我会这样做。问题是我不拥有代码,因此如果我或最终副本的所有者对该文件进行了更改,那么保持我的副本和最终副本同步将变得很棘手。

我想知道是否有办法使用类似模块的东西以不同的名称importlib导入核心模块?typing

我尝试了几件事,但它们总是失败,因为typing首先引用本地模块并typingsys.modules. 当存在同名模块时从内置库导入中的一些解决方案看起来很有希望,但由于递归错误而失败。

标签: pythonpython-3.x

解决方案


你是对的:更好的解决方案是重命名该模块。在导入系统周围进行黑客攻击可能会导致令人头疼的问题,以及更多的黑客攻击。打破格局:重命名模块,让大​​家开心。

穷人的解决办法是改变sys.path顺序。如果您设法将路径放在......./lib/site-packages包含包含typing模块的包的目录的路径之前,并且如果您在整个 Python 程序的任何其他模块导入 any之前这样做typing,它就可以工作。

这是我的设置:

stack_overflow/
├─ annoying/
│  ├─ __init__.py
│  ├─ innocent.py
│  ├─ typing.py
│  ├─ main.py
# file: innocent.py
import typing
print("'typing' imported")

abc: typing.List[str] = ["a", "b", "c"]
# file: main.py

import sys

print(sys.path)

import innocent

并且两者__init__.py都是typing.py空的。

当我执行我的主要内容时,我得到:

['C:\\PycharmProjects\\stack_overflow\\annoying', ... Python regular stuff ...]
'typing' imported
Traceback (most recent call last):
[...]
AttributeError: module 'typing' has no attribute 'List'

因为导入了错误的文件,由于sys.pathPythontypingannoying目录中搜索之前在其site-packages.

我现在把图书馆的路径放在最后:

# file: main.py

import sys

print(sys.path)
annoying_library_index_in_syspath, annoying_library_path = next((i, path) for i, path in enumerate(sys.path))
sys.path.pop(annoying_library_index_in_syspath)
sys.path.append(annoying_library_path)
print(sys.path)

import innocent

打印:

['C:\\PycharmProjects\\stack_overflow\\annoying', ... Python regular stuff ...]
[... Python regular stuff ..., 'C:\\PycharmProjects\\stack_overflow\\annoying']
'typing' imported

现在顺序颠倒了,Python优先typing从其导入site-packages,一切都按预期工作。但是,如果我有一个导入(甚至是可传递的)到typing在我更改之前导入 a 的模块sys.path,它将再次失败:

# file: main.py

import sys

import innocent  # raise AttributeError: module 'typing' has no attribute 'List'

print(sys.path)
annoying_library_index_in_syspath, annoying_library_path = next((i, path) for i, path in enumerate(sys.path))
sys.path.pop(annoying_library_index_in_syspath)
sys.path.append(annoying_library_path)
print(sys.path)

import innocent

但乱搞sys.path很容易出现错误、冲突、痛苦和悲伤。这就是为什么不鼓励为用户模块重用标准库名称的原因。所以请修复文件,这确实是最好的解决方案。


推荐阅读