Как импортировать из соседней директории

Структура проекта (условного):

example/
└── src/
    ├── a/
    │   └── here.py
    └── b/
        └── importing.py

src/b/importing.py

def sqr(x): return x * x

Способов импорта sqr из src/b/importing.py в src/b/here.py много, но все они приводят в ошибкам.

from example.b.importing import sqr

Ошибка: No module named 'example'.

from ..b.importing import sqr

Ошибка: attempted relative import with no known parent package.

from b.importing import sqr

Ошибка: No module named 'b'.

Добавлял __init__.py во все возможные папки, удалял — ничего не менялось. Добавлял setup.py:

from setuptools import setup

setup(name='example', version='1.0.0', package_dir='src')

Также безуспешно.

Как сделать этот импорт?


Ответы (1 шт):

Автор решения: Yan Wolf

И так, структура проекта:

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

src\a\ init.py

from src.a.main_a import foo_a

# импорт делает функцию foo_a() доступной напрямую из src.a.main_a

src\b\ init.py

from src.b.main_b import foo_b

src\a\main_a.py

def foo_a():
    print('С тобой говорит MAIN_A')

src\a\main_b.py

def foo_b():
    print('С тобой говорит MAIN_B')

main.py

from src.a import foo_a 
from src.b import foo_b

foo_a()
foo_b()

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

Что бы импортировать функцию из main_b.py в main_a.py:

main_a.py

from src.b import foo_Bb

foo_Bb()

src\b\ init.py

from src.b.main_b import foo_b

def foo_Bb():
    foo_b()

Немного науки:

Абсолютный и относительный импорт При абсолютном импорте используется полный путь (от начала корневой папки проекта) к желаемому модулю.

При относительном импорте используется относительный путь (начиная с пути текущего модуля) к желаемому модулю. Есть два типа относительных импортов:

При явном импорте используется формат from .<модуль/пакет> import X, где символы точки . показывают, на сколько директорий «вверх» нужно подняться. Одна точка . показывает текущую директорию, две точки .. — на одну директорию выше и т. д. Неявный относительный импорт пишется так, как если бы текущая директория была частью sys.path. Такой тип импортов поддерживается только в Python 2. В документации Python об относительных импортах в Python 3 написано следующее:

Единственный приемлемый синтаксис для относительных импортов — from .[модуль] import [имя]. Все импорты, которые начинаются не с точки ., считаются абсолютными.

Источник: What’s New in Python 3.0

В качестве примера допустим, что мы запускаем start.py, который импортирует a1, который импортирует other, a2 и sa1. Тогда импорты в a1.py будут выглядеть следующим образом:

Абсолютные импорты:

import other

import packA.a2

import packA.subA.sa1

Явные относительные импорты:

import other

from . import a2

from .subA import sa1

Неявные относительные импорты (не поддерживаются в Python 3):

import other

import a2

import subA.sa1

Учтите, что в относительных импортах с помощью точек . можно дойти только до директории, содержащей запущенный из командной строки скрипт (не включительно). Таким образом, from .. import other не сработает в a1.py. В результате мы получим ошибку ValueError: attempted relative import beyond top-level package.

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

Имейте в виду, что относительные импорты основаны на имени текущего модуля. Так как имя главного модуля всегда "main", модули, которые должны использоваться как главный модуль приложения, должны всегда использовать абсолютные импорты.

Источник: Python 2 и Python 3

→ Ссылка