Вопрос-Ответ

beyond top level package error in relative import [duplicate]

ошибка пакета верхнего уровня при относительном импорте [дубликат]

Кажется, здесь уже есть довольно много вопросов об относительном импорте в python 3, но после рассмотрения многих из них я все еще не нашел ответа на свою проблему. итак, вот вопрос.

У меня есть пакет, показанный ниже

package/
__init__.py
A/
__init__.py
foo.py
test_A/
__init__.py
test.py

и у меня есть одна строка в test.py:

from ..A import foo

теперь я нахожусь в папке package и запускаю

python -m test_A.test

Я получил сообщение

"ValueError: attempted relative import beyond top-level package"

но если я нахожусь в родительской папке package, например, я запускаю:

cd ..
python -m package.test_A.test

все в порядке.

Теперь мой вопрос таков: когда я нахожусь в папке package, и я запускаю модуль внутри подпакета test_A, поскольку test_A.test, насколько я понимаю, ..A поднимается только на один уровень, который все еще находится внутри package папки, почему он выдает сообщение с надписью beyond top-level package. Какова именно причина, вызывающая это сообщение об ошибке?

Переведено автоматически
Ответ 1

РЕДАКТИРОВАТЬ: В других вопросах есть лучшие / более последовательные ответы на этот вопрос:


Почему это не работает? Это потому, что python не записывает, откуда был загружен пакет. Итак, когда вы это делаете python -m test_A.test, это в основном просто отбрасывает информацию, которая test_A.test фактически хранится в package (т. е. package Не считается пакетом). Попытка from ..A import foo пытается получить доступ к информации, которой у него больше нет (например, к родственным каталогам загруженного местоположения). Концептуально это похоже на разрешение from ..os import path в файле в math. Это было бы плохо, потому что вы хотите, чтобы пакеты были разными. Если им нужно использовать что-то из другого пакета, то они должны ссылаться на них глобально с помощью from os import path и позволить python разобраться, где это находится с помощью $PATH и $PYTHONPATH.

Когда вы используете python -m package.test_A.test, то using from ..A import foo отлично решает проблему, потому что он отслеживает, что находится в package, и вы просто получаете доступ к дочернему каталогу загруженного местоположения.

ПОНЯТИЯ НЕ ИМЕЮ, Почему python не считает текущий рабочий каталог пакетом?, но, черт возьми, это было бы полезно.

Ответ 2
import sys
sys.path.append("..") # Adds higher directory to python modules path.

Попробуйте это.
У меня сработало.

Ответ 3

Предположение:
если вы находитесь в package каталоге, A и test_A являются отдельными пакетами.

Заключение:

..A импорт разрешен только внутри пакета.

Дополнительные примечания:
Сделать относительный импорт доступным только внутри пакетов полезно, если вы хотите принудительно размещать пакеты по любому пути, расположенному на sys.path.

Редактировать:


Я единственный, кто считает, что это безумие !? Почему вообще текущий рабочий каталог не считается пакетом? – Multihunter


Текущий рабочий каталог обычно находится в sys.path . Таким образом, все файлы в нем доступны для импорта. Это поведение начиная с Python 2, когда пакетов еще не существовало. Превращение запущенного каталога в пакет позволило бы импортировать модули как "import .A" и как "import A", которые тогда были бы двумя разными модулями. Возможно, это несоответствие, которое следует учитывать.

Ответ 4

Ни одно из этих решений не работало у меня в версии 3.6 со структурой папок типа:

package1/
subpackage1/
module1.py
package2/
subpackage2/
module2.py

Моей целью было импортировать из module1 в module2. Что, в конце концов, сработало для меня, как ни странно:

import sys
sys.path.append(".")

Обратите внимание на единственную точку в отличие от двухточечных решений, упомянутых до сих пор.


Редактировать: Следующее помогло прояснить это для меня:

import os
print (os.getcwd())

В моем случае рабочий каталог был (неожиданно) корневым каталогом проекта.

python