Экспорт на уровне пакетов, циклические зависимости

#python #import

Вопрос:

У меня есть следующий пакет:

 foo/
    __init__.py:
        from .body import UsefulClass
        from .another import AnotherClass

    body.py:

        from . import utll
        class UsefulClass:
            util.do_something()

    another.py:

        class AnotherClass: ...

    util.py:

        def do_something...

   
 

Идея заключается в том, что , когда кто-то импортирует foo , он должен иметь возможность использовать foo.UsefulClass , не беспокоясь о внутренней структуре пакета. Другими словами, я не хочу , чтобы они импортировались foo.body , просто foo .

Однако, когда я делаю from . import util body.py это , я также импортирую __init__.py , что, в свою очередь body , снова импортирует. Я понимаю, что python хорошо справляется с этой ситуацией, однако мне неудобно иметь эту явно циклическую зависимость.

Есть ли лучший способ экспортировать вещи на уровне пакета без создания циклических зависимостей при импорте?

PS: Я бы хотел избежать импорта в функции

Комментарии:

1. python выдаст импортер и сообщит вам о циклической зависимости. так что все в порядке. Кроме того, в некоторых ситуациях импорт в функции может помочь избежать проблем с циклической зависимостью.

2. Соответствует ли приведенная выше настройка вашей реальной проблеме? Если да, и вы столкнулись с ошибкой циклического импорта, это немного странно, потому что вышесказанное не должно приводить к ошибкам (как следует из ответа ниже). Какова ваша версия python, может быть, в прошлом что-то было по-другому?

Ответ №1:

Я думаю, что ваша первоначальная предпосылка неверна. Если вы сделаете import foo заявление с вашей текущей настройкой, __init__.py и body.py будет импортирован только один раз, как можно показать, поместив инструкцию печати в первую строку в каждом из этих файлов:

Макет каталога foo (я опустил another.py, так как его наличие или отсутствие не имеет значения):

введите описание изображения здесь

Файл __init__.py:

 print('__init__.py imported')

from .body import UsefulClass
 

Файл body.py:

 print('body.py imported')

from . import util

class UsefulClass:
    x = util.do_something()
 

Файл util.py:

 def do_something():
    return 9
 

И, наконец,:

 Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:57:54) [MSC v.1924 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import foo
__init__.py imported
body.py imported
>>> foo.UsefulClass.x
9
>>>