2

我有一个名为 的本地模块tokenize.py,它掩盖了一个同名的标准库模块。我只是在尝试导入外部模块(sklearn.linear_model)时才发现这一点,该模块反过来会import tokenize并希望获得标准库模块,但会获得我的本地模块。

这与当有同名的本地模块时如何在 Python 中访问标准库模块有关?,但设置不同,因为应用上述解决方案需要修改外部模块。

一个选项是重命名 local tokenize.py,但我不希望这样做,因为“tokenize”最能表达模块的作用。

为了说明这个问题,这里是一个模块结构的草图:

   \我的模块
      \__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'

导入外部模块时有什么方法可以抑制本地模块?

编辑:由于解决方案因 Python 版本而异的评论,将 python2.7 添加为标签

4

2 回答 2

4

问题不在于模块名称,而在于您正在运行一个模块,就像它是一个脚本一样。当 Python 运行脚本时,它会将脚本的包含目录添加为 中的第一个元素sys.path,因此来自任何地方的所有模块查找都将首先搜索该目录。

为避免这种情况,请让 Python 将其作为模块执行:

python -m my_module.use_tokenize

或者,当然,您可以将可执行脚本保留在模块层次结构之外。

于 2013-03-01T06:03:53.003 回答
0

解释器在其中搜索模块的路径列在sys.path. 为了防止第三方模块在导入时看到本地模块,我们.从路径中删除。这可以通过以下方式实现:

import sys
sys.path = sys.path[1:]
import sklearn.linear_model #using the original example.

tokenize但是,如果本地已经被导入,这将不起作用,并且它也会阻止本地tokenize被导入,即使我们恢复旧sys.path的如下:

import sys
old_path = sys.path
sys.path = sys.path[1:]
import sklearn.linear_model #using the original example.
sys.path = old_path

这是因为 Python 解释器维护了导入模块的内部映射,以便以后对同一模块的请求通过该映射来满足。这个映射对于解释器来说是全局的,所以import tokenize从运行它的任何代码中返回相同的模块——这正是我们试图改变的行为。为了实现这一点,我们必须改变这个映射。最简单的方法是简单地从 中删除相关条目sys.modules

import sys
old_path = sys.path
sys.path = sys.path[1:]
import sklearn.linear_model #using the original example.
sys.path = old_path
del sys.modules['tokenize'] #get of the mapping to the standard library tokenize
import tokenize #cause our local tokenize to be imported    
于 2013-03-04T00:06:22.770 回答