Я в пайтоне новичок, и с написанием своих модулей и подключением стороннего кода сразу возникло несколько вопросов.
1) Почему во Flask даже если я обращаюсь к вложенным модулям, наименование модуля все равно идет от корня?
Например, в корне лежит файл start.py, из которого я вызываю функцию, находящуюся в logic/mylogic.py. Также в папке logic лежит еще папка, а в ней какие-нибудь мои модули, например a.py. Относительно mylogic.py можно было бы сделать import a, но работает только import logic.a, даже если вызов идет из mylogic.py, который уже лежит в папке logic.
2) Если в интернете, на гитхабе, например, мне попадается какая-нибудь либа или чей-либо код, и я хочу его использовать, а этот код внутри ссылается на свои внутренние же модули, то мне приходится класть его только в корень. Стоит мне перенести его в какую-нибудь другую вложенную папку, как внутренние модули перестают работать, так как все их импорты опять же идут от корня (та же проблема, что и в предыдущем вопросе). Можно конечно, было бы переименовать все импорты, но в некоторых случаях (например, некоторые примеры tensoflow насчитывают тысячи и больше файлов) это дико неудобно, может быть, сущетсвует какой-то нормальный способ избежать зависимости от конкретной папки, где лежит модуль?
Спасибо!
В папке где лежит импортируемый модуль, надо создать пустой модуль __init__.py
Ну естественно если много под-папок то в каждой надо создать
Внутри папок делается относительный импорт
from . import my_module
Спасибо за ответ.
Пустые файлы __init__.py были созданы.
Внутри папок - вы имеете в виду, что надо переписывать все существующие импорты? А если файлов под тысячу или больше? Как обойтись без этого?
Если в интернете, на гитхабе, например, мне попадается какая-нибудь либа или чей-либо код, и я хочу его использовать, а этот код внутри ссылается на свои внутренние же модули, то мне приходится класть его только в корень. Стоит мне перенести его в какую-нибудь другую вложенную папку, как внутренние модули перестают работать, так как все их импорты опять же идут от корня (та же проблема, что и в предыдущем вопросе). Можно конечно, было бы переименовать все импорты, но в некоторых случаях (например, некоторые примеры tensoflow насчитывают тысячи и больше файлов) это дико неудобно, может быть, сущетсвует какой-то нормальный способ избежать зависимости от конкретной папки, где лежит модуль?
Никуда чужой код класть не надо. Надо использовать virtualenv (pipenv, conda, poetry) и устанавливать чужой код командой pip install tensorflow. Так же и со всеми остальными библиотеками.
Интересно!
А устанавливать так можно любой код? Должны они быть как-то оформлены специально, чтобы эта установка могла быть осуществлена?
И еще вопрос вдогонку - а что, если мне понадобится что-то в чужом коде изменить? Надо будет переустанавливать, или достаточно просто поменять код?
J_K, Любой правильно оформленный пакет python кода, да. Если вам надо изменить чужой код, то вы форкаете репозиторий на GitHub, делаете изменения, тестируете, создаете Pull Request авторам кода, они его мержат, выпускают новую версию, которую можно установить через pip.
А еще pip может устанавливать пакеты напрямую из git/mercurial/svn репозитория.
И в любом случае, код, который устанавливает pip, лежит в читаемом виде в virtualenv. Если так уж действительно надо что-то в нем быстро изменить, достаточно его найти в virtualenv и изменить все что надо. Естественно, что при пересоздании virtualenv или при обновлении пакета, правки будут потеряны. Но это и правильно. Тащить vendor зависимости напрямую в дерево исходников своего проекта — в 99% огромная ошибка.
Евгений, спасибо, но разве можно через pip устанавливать произвольный код? Вот у меня есть какие-то файлы на пайтоне, взятые из интернета, где авторы не оформляли их как пакеты и нигде не регистрировали, каким образом я могу выполнить установку?
В поиске меня не забанили, но там ответ найти не удалось. Везде говорится о том, как устанавливать "стандартные" пакеты, а не произвольные.
J_K, А в чем смысл таких исходников. Нормальные люди уже лет 15-20 так не делают. А библиотеки, написанные непонятно кем более 15 лет назад или неприменимы в современных условиях, или просто настолько плохи, что никому не нужны. Я пока исключений почти не видел, хотя это мой личный опыт, конечно.
Ну а если действительно что-то ценное, то вижу два варианта:
1) взять исходники, красиво оформить, выложить на GitHub и PyPI, для себя и для других
2) взять исходники и положить в корень своего проекта
Система импорта модулей и пакетов Python довольно проста и многократно описана. Если вы хотите положить их в какую-то внутреннюю папку, то, например, создаете папку vendor, кладете в нее библиотеку, и добавляете каким-либо образом папку vendor в переменную окружения PYTHONPATH или список sys.path в python (например, в файле конфигурации).
Евгений, хорошо, давайте оставим в покое сторонний код.
Есть у меня собственная внутренняя библиотека, скажем, посвященная работе с картами. Она лежит в папке mapwork, и, следовательно, все импорты внутри нее должны будут содержать ссылку на эту папку, например, import mapwork.point
Но вот по прошествии времени я решаю, что надо все такие либы переложить в одну папку, которая называется, скажем, businesslogic и содержит не только код для работы с картами, но и код для обработки данных.
И теперь все дружно перестает работать, потому что каждую строку import mapwork.point надо заменить на import businesslogic.mapwork.point
Какой есть способ избежать этой проблемы, чтобы папки можно было тасовать как угодно и сколько угодно раз без того, чтобы делать кучу лишних телодвижений? Ведь если я перемещу папку, надо опять переименовывать импорты и переменные окружения? Или нет?
J_K, внутри библиотеки можно использовать относительные import. В коде, использующем библиотеку придётся переименовывать. IDE, PyCharm, например, может переименовать автоматически. И вообще такие перемещения в жизни случаются редко и проблемой не являются.
Евгений, так вот вопрос в том и есть, как использовать относительные импорты? У меня получается только абсолютные и это очень неудобно.
Спасибо за PyCharm, буду знать.