【问题标题】:Why do I get an ImportError with PYTHONPATH set like this?为什么我会得到一个像这样设置 PYTHONPATH 的 ImportError?
【发布时间】:2014-08-08 14:45:39
【问题描述】:

我的PYTHONPATH 包含以下路径:

/path/to/venv/local/lib/python2.7/site-packages

并且我在站点包中有以下相关的目录结构:

graphite
  |
   --webapp
       |
        graphite
            |
             -- __init__.py
             --   .....

如果我是(venv) cd /path/to/venv/local/lib/python2.7/site-packages/graphite/webapp; ipython,那么使用import graphite 导入就没有问题。然而,如果cwd 不是那个,而是其他地方,我正在努力导入模块。例如,在我的 virtualenv 中:

(venv) cd ~
(venv) ipython

紧随其后

from graphite.webapp import graphite

from .graphite.webapp import graphite

抛出ImportError

当我的PYTHONPATH 包含上述目录时,为什么会这样?

【问题讨论】:

  • 在你的目录结构中,你写了grahite,这只是你的问题中的错字还是文件夹名称错误?
  • 外部石墨和webapp目录是否包含__init__.py文件?

标签: python importerror pythonpath


【解决方案1】:

您已经非常清楚地解释了情况(感谢您展示树)。我认为“grahite”是一个错字。你所观察到的都是意料之中的。您的/path/to/venv/local/lib/python2.7/site-packages/graphite 目录不是一个包,因为它不包含__init__.py 文件。

来自https://docs.python.org/2/tutorial/modules.html

__init__.py 文件是让 Python 处理 包含包的目录;这样做是为了防止 无意中使用通用名称(例如字符串)的目录 隐藏模块搜索路径中稍后出现的有效模块。

因此,尽管您的站点包中有一个graphite 目录,但它不被视为包。你说“我正在努力导入模块”,所以我猜你不是 100% 熟悉包和模块之间的区别,所以你真的应该再次查看引用的 Python 文档部分。

现在,如果您在您的 /path/to/venv/local/lib/python2.7/site-packages/graphite 目录中创建一个 __init__.py 文件,则一个 import graphite 从哪里——用你的话来说——“cwd 不是那个,而是 elswhere”将加载那个“上层”石墨包裹。请注意,这与取消引用 /path/to/venv/local/lib/python2.7/site-packages/graphite/webapp/graphiteimport graphite不同。这是两个不同的包,其中一个是另一个的子包。你需要决定从哪里导入哪一个,即你需要整理好你的包结构。

【讨论】:

  • 是的,这是一个错字。我知道在目录中需要__init__.py 来定义你所说的包(这就是为什么我注意在我的 OP 的目录树中显示它的原因)。鉴于此__init__.py 文件存在于graphite.webapp.graphite,那么为什么from graphite.webapp import graphite 会出现问题呢?子目录graphite应该是一个有效的包,那为什么不导入包path/to/venv/local/lib/python2.7/site-packages/graphite/webapp/graphite呢?
  • 包的外层目录也需要__init__.py?
  • Pythonnot 递归地扫描__init__.py 文件,然后将任何在Python 包以下(任何级别)包含此类文件的目录视为。我认为你同意这是有道理的。否则你的文件系统根目录将是一个 Python 包,对吧? ;)
  • 当然,但我想我很难看到问题只是点到带有__init__.py 的子目录,这是来自PYTHONPATH 某处的包,比如import path.to.package 没有pathto 目录也需要 __init__.py 文件。我们告诉python包在哪里,所以不需要递归扫描,我不太明白这种类型的约定如何意味着整个文件系统最终必须被视为一个python包,只是包目录与__init__.py...
  • import 语句中的名称绝不会纯粹表示/描述文件或目录名称。在 Python 世界中,您导入一个模块或一个包。这些只是碰巧组织在一个目录结构中。一个包也可以存在于另一个包中。导入——就像你的例子中的path.to.package——暗示有一个名为path的包和一个名为to的子包。我认为您确信导入系统主要通过名称和层次结构工作,而不是主要通过路径。
猜你喜欢
  • 2013-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多