Как выполнить относительный импорт в python

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

но получил ту же ошибку.

как я могу добиться этого? Это адекватный подход?

Edit: В Python 2

5 ответов


поиграв с ним немного больше, я понял, как его настроить, и ради конкретики я не буду использовать имена баров foo. Мой каталог проекта настроен как...

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) в этом пакете все было классно.


хотя, пока "материал" не находится в вашем пути python, у вас нет выбора, кроме добавления пути.

Если вы знаете уровень вашего script.py из вещей, которые вы можете сделать, например:

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

Я запускаю Python 3.4.2 в Windows 7 и вырвал свои волосы над этим.

при запуске любого из них:

python-m unittest python-m unittest discover

...Я бы получил ошибку "попытка относительного импорта за пределами пакета верхнего уровня".

для меня, решение было падать ".."в моем [test_stock.py]. Линия была: от..stock импорт Stock

изменить его: из импорта запасов Сток

.. и это работает.

папку структуру:

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

import ..foo..stuff.mylib должно быть ОК

EDIT снял расширение


С Пеп похоже, что вы не можете использовать относительный импорт для импорта файла, который не упакован.

таким образом, вам нужно будет добавить __init__.py чтобы наполнить и изменить импорт на что-то вроде from .mylib import *

однако ОПТОСОЗ, похоже, не учитывает, что mylib упакован в модуль. Таким образом, вам может потребоваться изменить способ вызова функций библиотеки.

другая альтернатива-переместить mylib в подпакет и импортировать его as from .libpackage import mylib