Как сделать импорт из каталога уровнем выше?
У меня есть файлы
abc/bot.py
payment.py
bot.py
Я запускаю abc/bot.py и мне нужно импортировать payments.py, то есть каким-то образом перейдите в каталог выше. Я пытался
от.. импорт платежа
из ..импорт платежа отправить
Я получил сообщение об ошибке ImportError: предпринята попытка относительного импорта без известного родителя, и все. Что делать?
Ответы (2 шт):
Можно использовать os.chdir(path) чтобы указать точный путь/каталог который вам нужен
Костыльный способ: добавить внешнюю папку в переменную окружения PYTHONPATH, тогда можно будет из нее импортировать просто по имени:
abc/bot.py:
import sys
from pathlib import Path
# __file__ - путь текущего файла, из него получаем путь к директории выше
sys.path.append(str(Path(__file__).parent.parent))
import payment
Другой вариант: считать, что вся папка, где лежит код - это пакет, и запускать код в ней как модуль.
Структура каталогов:
.
└── some_bot
├── abc
│ └── bot.py
├── bot.py
└── payment.py
Файл some_bot/abc/bot.py:
from ..payment import send
# Или from some_bot.payment import send
send()
Файл some_bot/payment.py:
def send():
print("send something")
Из командной строки, находясь в директории снаружи some_bot, запускаем:
> python3 -m some_bot.abc.bot
send something
Ключевое тут: чтобы работал абсолютный (from some_bot.payment import send) или относительный (from ..payment import send) импорт, код должен запускаться как пакет, снаружи пакета. Не двойным кликом по файлу abc/bot.py или командой python abc/bot.py, а через python с ключом -m, иначе будет ошибка ImportError (при относительном импорте - что не известен родительский пакет, при абсолютном - что пакет с таким именем не найден).
В целом, если положить снаружи пакета some_bot модуль python, и в нем прописать import some_bot.abc.bot, то это будет аналогично запуску python -m some_bot.abc.bot из командной строки.
Вообще, для простого проекта я бы не заморачивался с пакетами, а просто все запускаемые файлы перенес на внешний уровень (логично же, чтобы "пульт управления" был на виду, а не был спрятан где-то глубоко в папках), а вспомогательные разложил по папкам при необходимости, тогда из запускаемых файлов будет работать "простой" импорт.
Про пакеты можно почитать, например, тут: Пакеты Python — создание и доступ
Только я не добавлял файл __init__.py, есть отличия в пакетах с таким файлом и без него, но в данном случае это не критично.
Детально про __init__.py можно почитать тут: Is __init__.py not required for packages in Python.