我有一个名为 tokenize.py
的本地模块,它掩盖了一个同名的标准库模块 . 我只是在尝试导入外部模块(sklearn.linear_model)时发现了这一点,而外部模块又是 import tokenize
并期望获得标准库模块,而是获取我的本地模块 .
这与How to access a standard-library module in Python when there is a local module with the same name?有关,但设置不同,因为应用上述解决方案需要修改外部模块 .
一个选项是重命名本地 tokenize.py
,但我不希望这样做,因为"tokenize"最能表达模块的作用 .
为了说明问题,这里是模块结构的草图:
\my_module
\__init__.py
\tokenize.py
\use_tokenize.py
在use_tokenize.py中,有以下导入:
import sklearn.linear_model
调用 python my_module/use_tokenize.py
时会导致以下错误:
Traceback (most recent call last):
File "use_tokenize.py", line 1, in <module>
import sklearn.linear_model
<...>
File "<EDITED>/lib/python2.7/site-packages/sklearn/externals/joblib/format_stack.py", line 35, in <module>
generate_tokens = tokenize.tokenize
AttributeError: 'module' object has no attribute 'tokenize'
导入外部模块时有没有办法抑制本地模块?
编辑:添加python2.7作为标记,因为解决方案因Python版本而异
2 回答
问题不在于模块名称,而是在运行类似于脚本的模块 . 当Python运行脚本时,它会将脚本的包含目录添加为
sys.path
中的第一个元素,因此从任何地方进行的所有模块查找都将首先搜索该目录 .要避免这种情况,请让Python将其作为模块执行:
或者,当然,您可以将可执行脚本保留在模块层次结构之外 .
解释器搜索模块的路径列在
sys.path
中 . 为防止第三方模块在导入时看到本地模块,我们从路径中删除.
. 这可以通过以下方式实现:但是,如果已导入本地
tokenize
,这将无效,并且即使我们恢复旧的sys.path
,它也将阻止导入本地tokenize
,如下所示:这是因为Python解释器维护导入模块的内部映射,以便从该映射实现对同一模块的后续请求 . 这个映射对于解释器是全局的,因此
import tokenize
从运行它的任何代码返回相同的模块 - 这正是我们试图改变的行为 . 为此,我们必须改变这种映射 . 最简单的方法是从sys.modules
删除相关条目 .