Обновление – Обновленная версия этого проекта здесь – https://github.com/unfor19/python-project/wiki
К концу этого поста в блоге вы сможете:
- Создать хорошо структурированный проект Python
- Используйте относительный и абсолютный импорт в проекте Python
- Вызовать конкретный модуль из командной линии (терминал)
Ссылка на репозиторий GitHub – Unfor19/Python-Project
Структура проекта Python, относительный импорт, абсолютный импорт, пакеты и модули. Давайте сделаем это проще.
Начиная
Выполнение модулей из корневого каталога проекта (пакет верхнего уровня)
- main.py
meirgabay@~/python-project (master)$ python main.py My Path: python-project/main.py Insert your name: willy Hello willy meirgabay@~/python-project (master)$ python -m appy My Path: python-project/appy/__main__.py Insert your name: willy Hello willy
- appy/core/app.py
# Contains relative imports - `..utils.message` meirgabay@~/python-project (master)$ python appy/core/app.py Traceback (most recent call last): File "appy/core/app.py", line 1, infrom ..utils import message ImportError: attempted relative import with no known parent package meirgabay@~/python-project (master)$ python -m appy.core.app My Path: python-project/appy/core/app.py Insert your name: willy Hello willy
- Appy/utils/message.py
# Doesn't contain relative imports, so no exceptions were raised meirgabay@~/python-project (master)$ python appy/utils/message.py My Path: python-project/appy/utils/message.py meirgabay@~/python-project (master)$ python -m appy.utils.message My Path: python-project/appy/utils/message.py
Вопросы и ответы (Q & A)
Проект, пакеты, модули и сценарии, что они?
- Проект – каталог, также известный как пакет верхнего уровня, который содержит пакеты и модули
- Пакет (в проекте) – каталог, который содержит модули и/или пакеты (подзадачи)
- Скрипт – сценарий Python (
.py
), который можно исключить из терминала - Модуль – сценарий Python (
.py
), который может быть импортирован с помощьюИмпорт
иот
Как насчет пакетов, которые не являются частью проекта?
- Пакет (встроенный) – пакет, который поставляется с Python и может быть импортирован с помощью
Импорт
иот
- Пакет (PIP) – пакет, который установлен с Pip и может быть импортирован с
Импорт
иот
Анкет Подумайте об этом, PIP выступает за Упаковка Я nstaller для P yton
Как им импортировать пакеты и модули, которые я создал?
Пакеты и модули Python Project могут быть импортированы с помощью Относительные пути из любого модуля, который Часть того же проекта Анкет Пример доступен в appy/core/app.py
Если вы собираетесь импортировать пакет или модуль, который является Не часть того же проекта , вам придется использовать Абсолютные пути Анкет Это можно сделать с ImportLib , см. Это Stackoverflow Ответ Анкет
Нужен ли мне файл __init__.py?
- Короткий ответ – нет
- В предыдущих версиях Python вы должны были создать
__init__.py
Файл в каждом каталоге, который вы хотите импортировать в качестве пакета, их называли обычные пакеты Анкет Из версии 3.3+ это больше не требуется – Неявные пакеты пространства имен , пакеты без__init__.py
Файл называется Пакеты пространства имен Анкет
Почему относительный импорт поднимает проблему в пилинте?
Ошибка – Попытка относительного импорта за пределами верхнего уровня PackagePylint (относительный уровень Beyond-Top)
- Короткий ответ – Я не знаю
- Все, что я могу сказать, это то, что это не происходит с Flake8
Можно ли вызвать функцию из терминала?
Короткий ответ – это зависит
Попытка вызвать функцию из терминала, например
appy.core.app.main ()
, поднимет исключение ModulEnotFound. Пакет должен быть импортирован до вызывая одну из его функций.
meirgabay@~/python-project (master)$ python -m appy.core.app.main /Users/meirgabay/.pyenv/versions/3.8.2/Python.framework/Versions/3.8/bin/python: Error while finding module specification for 'appy.core.app.main' (ModuleNotFoundError: __path__ attribute not found on 'appy.core.app' while trying to find 'appy.core.app.main')
- Поскольку вы не можете вызвать
main ()
прямо из терминала, вызывая его изЕсли __main__
Блок позволяет выполнять его из терминала. Можно передать аргументы, но это немного уродливое, Прочитайте документы Чтобы узнать, как. Следующий пример пытается выполнить модульappy.core.app
, что, в свою очередь, называют егоЕсли __main__
блокировать
meirgabay@~/python-project (master)$ python -m appy.core.app My Path: python-project/appy/core/app.py Insert your name: willy Hello willy
- Если
Pwd
является подкаталогом проекта, такой какPython-Project/Appy
Попытка выполнить модуль, который содержит относительный импорт, поднимет исключение ниже. Помните, вашPwd
Всегда должен быть корневым каталогом проекта, в данном случае этоPython-Project
Анкет
# PWD is `appy` meirgabay@~/python-project/appy (master)$ python -m core.app Traceback (most recent call last): File "/Users/meirgabay/.pyenv/versions/3.8.2/Python.framework/Versions/3.8/lib/python3.8/runpy.py", line 193, in _run_module_as_main return _run_code(code, main_globals, None, File "/Users/meirgabay/.pyenv/versions/3.8.2/Python.framework/Versions/3.8/lib/python3.8/runpy.py", line 86, in _run_code exec(code, run_globals) File "/Users/meirgabay/python-project/appy/core/app.py", line 1, infrom ..utils import message ValueError: attempted relative import beyond top-level package
- Это не происходит при вызовах
Сообщение
, так какСообщение
не использует относительный импорт
meirgabay@~/python-project/appy (master)$ python utils/message.py My Path: python-project/appy/utils/message.py meirgabay@~/python-project/appy (master)$ python -m utils.message My Path: python-project/appy/utils/message.py
- Вызов функции из терминала также возможна с помощью
-c
флаг. Сюрприз, можно провести аргументы более интуитивно понятным образом, например,app.main (my_arg1, my_arg2)
meirgabay@~/python-project (master)$ python -c "import appy.core.app as app; app.main()" Insert your name: willy Hello willy
Каковы доступные флаги командной строки в Python?
- Прочитайте документы – Использование cmdline
- В этом уроке мы использовали оба
-c
и-m
флаги
Почему можно выполнить Python -m Appy?
Appy/__ main__.py Файл действует как Если __main__
Код фрагмент, но на пакетах. Это позволяет Appy
пакет для выполнения с Python -m
или с пробежка
meirgabay@~/python-project (master)$ python -m appy My Path: python-project/appy/__main__.py Insert your name: willy Hello willy
Что такое Runpy и почему вы используете его в main.py?
Runpy
Пакет предоставляет возможность запускать модули из модуля (сценарий Python).
main.py
import runpy def main(): # import a package, and pass all current global variables to it appy_package = runpy.run_module(mod_name="appy", init_globals=globals()) # import the function script_path() from the submodule message, and execute it appy_package['message'].script_path(__file__) # execute the function main(), which is located in appy/__main__.py appy_package['main']() if __name__ == "__main__": main()
Что за глобальные ()?
Официальное определение из док
Верните словарь, представляющий текущую таблицу глобальных символов. Это всегда словарь текущего модуля (внутри функции или метода, это модуль, где он определяется, а не модуль, из которого он называется).
Пример – развернуть/коллапс
meirgabay@~/python-project (master)$ python Python 3.8.2 (default, Jun 30 2020, 19:04:41) [Clang 11.0.3 (clang-1103.0.32.59)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> globals() {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': , '__spec__': None, '__annotations__': {}, '__builtins__': }
Почему у вас есть странный путь с Pyenv, когда вы запускаете Python?
В некоторых примерах вы, возможно, видели, что мой двоичный файл Python находится в
/Users/meirgabay/.pyenv/versions/3.8.2/Python.framework/Versions/3.8/bin/python
Это потому, что я использую Pyenv , официальное определение из документов
Pyenv позволяет легко переключаться между несколькими версиями Python . Это просто, ненавязчивая и следует за традицией UNIX одноцелевых инструментов, которые хорошо делают одну вещь.
Pyenv отлично подходит для проверки обратной совместимости
Переход на другую версию
- Установите соответствующую версию –
Установка Pyenv 3.7.7
- Запустить
Экспорт.7.7
- Для повседневного использования
- Установите соответствующую версию –
Установка Pyenv 3.8.2
- Добавить
Экспорт.8.2
к вашему терминалудольдо
или_profile
($ home/.bashrc
,$ home/.bash_profile
,$ Главная/.zshrc
)
Примеры – развернуть/коллапс
meirgabay@~/python-project (master)$ export PYENV_VERSION= meirgabay@~/python-project (master)$ pyenv versions * system (set by /Users/meirgabay/.pyenv/version) # default OS Python 3.7.7 3.8.2 meirgabay@~/python-project (master)$ python --version Python 2.7.16 # switching to a different version meirgabay@~/python-project (master)$ export PYENV_VERSION=3.7.7 meirgabay@~/python-project (master)$ python --version Python 3.7.7 # day to day use meirgabay@~/python-project (master)$ source ~/.bash_profile meirgabay@~/python-project (master)$ python --version Python 3.8.2
Есть ли хорошая основа для создания Python CLI?
- Короткий ответ – да! Больше, чем несколько!
- Щелчок Framework удивительно! Я использовал его в GitHubSecrets и фригга ПРИМЕЧАНИЕ : Вы обнаружите, что у меня есть
__init__.py
Файлы в моих проектах, это неприятная старая привычка, я обещаю, что брошу их, обещаю - Узнайте больше о доступных фреймворках Python CLI в этом отличном сообщении в блоге – Построение красивых интерфейсов командной строки с Python
Где я могу найти хорошо структурированный проект Python?
- SampleProject – Официальный проект Python Sample
- Django – сложный проект Python
- Запросы – Проект некомплекса Python
Последние слова
Я надеюсь, что этот пост в блоге помог вам понять, как создать хорошо структурированный проект Python, и, если это так, то сердце, хлопает, звезды и поделиться!
Оригинал: “https://dev.to/unfor19/python-project-structure-relative-imports-absolute-imports-packages-and-modules-let-s-make-it-simpler-6lk”