如何在python中完成相对导入

问题描述 投票:23回答:6
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中

python python-2.x relative-path python-packaging
6个回答
29
投票

经过一番摆弄之后,我意识到了如何设置它,并且出于特殊性考虑,我将不使用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)移到该程序包中,一切就变得很笨拙。


11
投票

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

例如,如果您知道脚本的水平,可以执行以下操作:

import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))

7
投票

我正在Windows 7上运行Python 3.4.2,并为此扯掉了头发。

运行以下任何一个时:

python -m unittestpython -m unittest发现

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

对我来说,解决方案是在我的[test_stock.py]中删除“ ..”。该行是:从..stock进口库存

更改为:从库存进口库存

..并且有效。

文件夹结构:

C:\
  |
  +-- stock_alerter
             |
             +-- __init__.py
             +-- stock.py
             |
             \-- tests
                   |
                   +-- __init__.py
                   \-- test_stock.py

1
投票

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

编辑删除了扩展名


1
投票

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

因此,您需要在内容中添加__init__.py,并将导入内容更改为from .mylib import *之类的内容>

但是,PEP似乎不容许将mylib打包在模块中。因此,可能需要更改调用库函数的方式。

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


0
投票

如果您使用的是Linux或类似的* nix,则可以使用符号链接对其进行破解。

© www.soinside.com 2019 - 2024. All rights reserved.