24
stuff/
    __init__.py
    mylib.py
    Foo/
        __init__.py
        main.py
        foo/
            __init__.py
            script.py

script.py想进口mylib.py

这只是一个示例,但实际上我只想在父目录中进行模块的相对导入。我尝试了各种方法并收到此错误...

Attempted relative import beyond toplevel package

我在某处读到程序启动的脚本不应该在包中,我尝试像这样修改结构......

stuff/
    mylib.py
    foo.py // equivalent of main.py in above
    foo/
        __init__.py
        script.py

但得到了同样的错误。

我怎样才能做到这一点?这甚至是一种适当的方法吗?

编辑:在 Python 2 中

4

6 回答 6

28

再摆弄一下之后,我意识到如何设置它,为了具体起见,我不会使用 foo bar 名称。我的项目目录设置为...

tools/
    core/
        object_editor/
            # files that need to use ntlib.py
            editor.py # see example at bottom
            __init__.py
        state_editor/
            # files that need to use ntlib.py
            __init__.py
        ntlib.py
        __init__.py # core is the top level package
    LICENSE
    state_editor.py # equivalent to main.py for the state editor
    object_editor.py # equivalent to main.py for the object editor

一条线object_editor.py看起来像...

from core.object_editor import editor

一条线editor.py看起来像...

from .. import ntlib

或者

from core import ntlib

关键是在我在问题中给出的示例中,“主”脚本是从包中运行的。core一旦我将它移出,创建了一个特定的包ntlib

于 2011-01-11T09:46:41.760 回答
14

尽管只要“东西”不在您的 python PATH 中,您就别无选择,只能添加路径。

如果你从你可以做的事情中知道你的 script.py 的级别,例如:

import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
于 2011-01-11T08:56:48.320 回答
7

我在 Windows 7 上运行 Python 3.4.2 并为此撕毁了我的头发。

运行其中任何一个时:

python -m unittest python -m unittest 发现

...我会收到“尝试相对导入超出顶级包”错误。

对我来说,解决方案是在我的 [test_stock.py] 中删除“..”。该行是: from ..stock import Stock

将其更改为:从库存导入库存

..它有效。

文件夹结构:

C:\
  |
  +-- stock_alerter
             |
             +-- __init__.py
             +-- stock.py
             |
             \-- tests
                   |
                   +-- __init__.py
                   \-- test_stock.py
于 2015-05-15T15:28:40.787 回答
1

import ..foo..stuff.mylib应该可以

编辑取消了扩展

于 2011-01-11T08:26:44.103 回答
1

PEP看来,您不能使用相对导入来导入未打包的文件。

所以你需要添加一个__init__.py东西并将你的导入更改为类似from .mylib import *

然而,PEP 似乎不允许将 mylib 打包在一个模块中。因此,您可能需要更改调用库函数的方式。

另一种选择是将 mylib 移动到子包中并将其导入为from .libpackage import mylib

于 2011-01-11T09:45:06.850 回答
0

如果您使用的是 Linux 或类似的 *nix,您可以使用符号链接来破解它。

stuff/
    mylib.py
    foo.py // equivalent of main.py in above
    foo/
        script.py
        mylib.py  ->  ../mylib.py
    foo2/
        script2.py
        mylib.py  ->  ../mylib.py

这可能不是一个好的模式。

就我而言,我选择了它,因为我有多个依赖于同一个库的可执行文件,需要将它们放入单独的目录中。

新的可执行测试的实现不应该要求测试编写者对 python 导入有深入的了解。

tests/
    common/
        commonlib.py
    test1/
        executable1.py
        executable2.py
        commonlib.py -> ../common/commonlib.py
    test2/
        executable1.py
        executable2.py
        commonlib.py -> ../common/commonlib.py


于 2019-02-05T14:23:05.103 回答