如何在python中完成相对导入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4655526/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 16:46:54  来源:igfitidea点击:

How to accomplish relative import in python

pythonpython-2.xrelative-pathpython-packaging

提问by random

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

script.pywants to import mylib.py

script.py想进口 mylib.py

This is just an example, but really I just want to do a relative import of a module in a parent directory. I've tried various things and get this error...

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

Attempted relative import beyond toplevel package

Attempted relative import beyond toplevel package

I read somewhere that the script from where the program starts shouldn't in the package, and I tried modifying the structure for that like so...

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

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

but got same error.

但得到了同样的错误。

How can I accomplish this? Is this even an adequate approach?

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

Edit: In Python 2

编辑:在 Python 2 中

采纳答案by random

After fiddling with it a bit more, I realized how to set it up, and for the sake of specificity I won't use foo bar names. My project directory is set up as...

稍微摆弄了一下之后,我意识到了如何设置它,为了具体起见,我不会使用 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

A line in object_editor.pylooks like...

一行object_editor.py看起来像...

from core.object_editor import editor

A line in editor.pylooks like...

一行editor.py看起来像...

from .. import ntlib

or alternatively

或者

from core import ntlib

The key is that in the example I gave in the question, the "main" script was being run from within the package. Once I moved it out, created a specific package (core), and moved the library I wanted the editors to share (ntlib) into that package, everything was hunky-dory.

关键是在我在问题中给出的示例中,“主”脚本是从包中运行的。一旦我将它移出,创建了一个特定的包 ( core),并将我希望编辑器共享的库 ( ntlib) 移到该包中,一切都是笨拙的。

回答by tekknolagi

import ..foo..stuff.mylibshould be ok

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

EDIT took off the extension

EDIT 取消了扩展

回答by Torsten Engelbrecht

though as long "stuff" is not in your python PATH you got no choice than adding the path.

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

If you know the level of your script.py from stuff you can do for example:

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

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

回答by Dunes

From the PEPit appears that you cannot use a relative import to import a file that is not packaged.

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

So you would need to add a __init__.pyto stuff and change your imports to something like from .mylib import *

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

However, the PEP seems to make no allowance to keep mylib packaged up in a module. So you might be required to change how you call your library functions.

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

Another alternative is to move mylib into a subpackage and import it as from .libpackage import mylib

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

回答by Allen May

I'm running Python 3.4.2 on Windows 7 and tore my hair out over this.

我在 Windows 7 上运行 Python 3.4.2 并为此烦恼。

When running either of these:

运行其中任何一个时:

python -m unittest python -m unittest discover

python -m unittest python -m unittest 发现

...I would get the 'Attempted relative import beyond toplevel package' error.

...我会得到'尝试相对导入超出顶级包'错误。

For me, the solution was dropping the ".." in my [test_stock.py]. The line was: from ..stock import Stock

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

Changed it to: from stock import Stock

改为:从库存进口库存

.. and it works.

..它的工作原理。

Folder structure:

文件夹结构:

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

回答by TheMeaningfulEngineer

If you're on Linux or perhaps a similar *nix, you can hack this with symlinks.

如果您使用的是 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

This is likely not a good pattern to follow.

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

In my case I opted for it because I had multiple executables dependent on the same library that needed to be put into separate directories.

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

Implementation of new executable tests shouldn't require the test writer to have a deep understanding of python imports.

新的可执行测试的实现不应该要求测试编写者对 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