【问题标题】:Python import from sibling directories从同级目录导入 Python
【发布时间】:2018-09-10 14:05:06
【问题描述】:

免责声明:在搜索了大量非常相似的提要后,最终都解决了一个略有不同的问题,我想我必须提出一个新问题(尽管我确信存在在某处回答->如果您知道,请指出;)

问题:我正在使用 Python 2,正在用这棵树构建一个项目:

project
├── __init__.py
├── foo  
│   └── __init__.py
│   └── bar   
│       └── __init__.py
├── notebooks   
│   └── __init__.py
│   └── skript.py
└── test
    └── __init__.py
    └── foo   
        └── __init__.py
        └── bar   
            └── __init__.py
            └── file.py

现在我想从project/notebooks/skript.py 中加载 test.foo.bar。因此,我在那个脚本中做

import sys
sys.path.append('../')

如果我然后运行

import test.foo.bar  # or: import test.foo

python 告诉我

ImportError: No module named foo.bar

(或分别为ImportError: No module named foo)。有趣的是,import test 不会抛出错误,但如果我再这样做 test.foo 它会抛出 AttributeError: 'module' object has no attribute 'foo'

所以我想知道,这里出了什么问题以及如何解决它?


编辑

另外,我尝试将此添加到skript.py

import sys
import os
MYDIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(MYDIR,'../test'))
sys.path.append(os.path.join(MYDIR,'../test/foo'))
sys.path.append(os.path.join(MYDIR,'../test/foo/bar')) #I am not sure this is entirely needed

如下所述。不过,

import test.foo.bar.file

或 从 test.foo.bar 导入文件 只是屈服

ImportError: No module named foo.bar

sys.path.append('../test/foo/bar')
import test.foo.bar.file

我仍然不知道出了什么问题?

【问题讨论】:

  • 如果您将../ 路径附加到python 路径,您将附加project 路径,而不是bar 模块所在的路径,您应该添加./test/foo/bar 路径。
  • 您的错误只抱怨foo.bar,而不是test.foo.bartest 是否明确导入 foo.bar

标签: python python-import


【解决方案1】:

sys.path 混在一起并不是一个好主意。

由于您的计划似乎是同时使用来自notebooksfootest(可能只包含Jupyter 笔记本),因此最简洁的解决方案是将footest 作为软件包安装。

从您的顶级目录中删除__init__.pynotebooks,因为您不想导入它们。然后将setup.py 添加到您的顶级目录。由于您的测试特定于 foo,因此您应该将它们重命名为 foo_test 或将它们移动到 foo 本身。

最小的setup.py 看起来像这样

from setuptools import setup

setup(name='foo',
      version='0.1',
      description='descroption of fo',
      author='you',
      author_email='your@mail',
      packages=['foo','test_foo])

然后你可以在你的顶级目录中简单地pip install -e .,它将被安装到你当前的 virtualenv 中。如果你没有使用 virtualenvs,你应该pip install --user -e .

【讨论】:

  • 甜蜜!这就是我要找的:)
【解决方案2】:

它应该适用于

from test import foo

但是你必须在你的项目目录中添加一个__init__.py

对于 Python 3,它将是:

from .test import foo

如果你在文件夹名称前使用点,python会在你正在处理的文件所在的同一目录中搜索文件。

对不起,我的英语不好。

【讨论】:

  • Hmm.. 这给了我:>>> from .test import foo Traceback(最近一次调用最后):文件“”,第 1 行,在 ValueError:尝试相对导入在非包装中
  • 你需要一个__init__.py项目目录下的文件吗?
  • 是的,没错。项目目录下有__init__.py文件吗?
  • 我只是添加了一个,但它并没有改变任何事情:/
  • 我现在在任何目录中都有 init.py 文件仍然没有区别。 (init 和 init 之间实际上有区别吗?)
【解决方案3】:

您使用的是 IDE 吗?如果是这样,请将项目属性中 Python 解释器的路径添加到所有主要包(foo、test、notebooks)。否则尝试像这样显式地将 bar 包添加到 sys 路径中

import sys
import os
MYDIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(MYDIR,'test'))
sys.path.append(os.path.join(MYDIR,'test/foo'))
sys.path.append(os.path.join(MYDIR,'test/foo/bar')) #I am not sure this is entirely needed

【讨论】:

  • 一般来说,我使用 IDE,但目前正在使其在 IDE 之外工作(特别是我想将 Jupyter 笔记本放入 notebooks 目录,以便使用测试和源文件/方法) .我尝试了您的建议,但仍然无法正常工作(另外,我想您还应该导入操作系统;)。在您编写它时,它实际上对测试目录有什么作用?
  • 哦,对了,你在 notebooks 工作,而不是在 tests 工作,我会更新我的答案。也是的,我忘了导入os
  • 我仍然得到美丽的ImportError: No module named foo.bar.file。但我仍然想知道你写的东西实际上是做什么的。 MYDIR 不只是文件的路径,所以在这种情况下,就像.../project/notebooks 这样sys.path.append(os.path.join(MYDIR,'test')) 将返回.../project/notebooks/test 等?这甚至不是一条有效的路径?
  • MYDIR 是您当前正在执行的文件的路径,但我使用它来获得我要附加的包的绝对路径,尝试在每次测试之前添加../
  • 我明白了。但是,即使在每个 test 之前添加 ../ 也无济于事。另外我认为原则上将笔记本的父目录添加到 sys.path 就足够了。因为然后解释器应该清楚诸如import test.foo.bar 之类的语句?无论如何,我将对问题进行编辑,以便同时注意更改...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-31
  • 1970-01-01
  • 1970-01-01
  • 2012-05-03
  • 2019-06-19
相关资源
最近更新 更多