как код превратить в программу python
Как превратить скрипт на Python в «настоящую» программу при помощи Docker
Никого не интересует, умеете ли вы разворачивать связанный список — всем нужно, чтобы можно было легко запускать ваши программы на их машине. Это становится возможным благодаря Docker.
Для кого предназначена эта статья?
Вам когда-нибудь передавали код или программу, дерево зависимостей которой напоминает запутанную монтажную плату?
Как выглядит управление зависимостями
Без проблем, я уверен, что разработчик любезно предоставил вам скрипт установки, чтобы всё работало. Итак, вы запускаете его скрипт, и сразу же видите в оболочке кучу сообщений логов ошибок. «У меня на машине всё работало», — обычно так отвечает разработчик, когда вы обращаетесь к нему за помощью.
Docker решает эту проблему, обеспечивая почти тривиальную портируемость докеризованных приложений. В этой статье я расскажу, как быстро докеризировать ваши приложения на Python, чтобы ими можно было легко делиться с любым человеком, у которого есть Docker.
В частности, мы рассмотрим скрипты, которые должны работать как фоновый процесс.
Репозитории Github и Docker
Если вам более удобна наглядность, то изучите репозитории Github и Docker, где будет хоститься этот код.
Но… почему Docker?
Контейнеризацию можно сравнить с размещением вашего ПО в грузовом контейнере, обеспечивающем стандартный интерфейс для компании-грузоперевозчика (или другого компьютера-хоста), который позволяет взаимодействовать с ПО.
Контейнеризация приложений на самом деле является золотым стандартом портируемости.
Общая схема Docker/контейнеризации
Контейнеризация (особенно при помощи docker) открывает перед вашим программным приложением огромные возможности. Правильно контейнеризированное (например, докеризированное) приложение можно развёртывать с возможностью масштабирования через Kubernetes или Scale Sets любого поставщика облачных услуг. И да, об этом мы тоже поговорим в следующей статье.
Наше приложение
В нём не будет ничего особо сложного — мы снова работаем с простым скриптом, отслеживающим изменения в каталоге (так как я работаю в Linux, это /tmp ). Логи будут передаваться на stdout, и это важно, если мы хотим, чтобы они отображались в логах docker (подробнее об этом позже).
main.py: простое приложение мониторинга файлов
Эта программа будет выполняться бесконечно.
Как обычно, у нас есть файл requirements.txt с зависимостями, на этот раз только с одной:
Создаём Dockerfile
В моей предыдущей статье мы создали скрипт процесса установки в Makefile, благодаря чему им очень легко делиться. На этот раз мы сделаем нечто подобное, но уже в Docker.
Нам необязательно вдаваться в подробности устройства и работы Dockerfile, об этом есть более подробные туториалы.
Краткое описание Dockerfile — мы начинаем с базового образа, содержащего полный интерпретатор Python и его пакеты, после чего устанавливаем зависимости (строка 6), создаём новый минималистичный образ (строка 9), копируем зависимости и код в новый образ (строки 13–14; это называется многоэтапной сборкой, в нашем случае это снизило размер готового образа с 1 ГБ до 200 МБ), задаём переменную окружения (строка 17) и команду исполнения (строка 20), на чём и завершаем.
Сборка образа
Завершив с Dockerfile, мы просто выполняем из каталога нашего проекта следующую команду:
Запуск образа
После завершения сборки можно начинать творить магию.
Один из самых замечательных аспектов Docker заключается в том, что он предоставляет стандартизованный интерфейс. Так что если вы правильно спроектируете свою программу, то передавая её кому-то другому, достаточно будет сказать, что нужно изучить docker (если человек ещё его не знает), а не обучать его тонкостям устройства вашей программы.
Хотите увидеть, что я имею в виду?
Команда для запуска программы выглядит примерно так:
Здесь многое нужно объяснить, поэтому разобьём на части:
-d — запуск образа в detached mode, а не в foreground mode
—restart=always — при сбое контейнера docker он перезапустится. Мы можем восстанавливаться после аварий, ура!
—e DIRECTORY=’/tmp/test’ — мы передаём при помощи переменных окружения каталог, который нужно отслеживать. (Также мы можем спроектировать нашу программу на python так, чтобы она считывала аргументы, и передавать отслеживаемый каталог таким способом.)
-v /tmp/:/tmp/ — монтируем каталог /tmp в каталог /tmp контейнера Docker. Это важно: любой каталог, который мы хотим отслеживать, ДОЛЖЕН быть видимым нашим процессам в контейнере docker, и именно так это реализуется.
directory-monitor — имя запускаемого образа
После запуска образа его состояние можно проверять с помощью команды docker ps :
Docker создаёт crazy-имена для запущенных контейнеров, потому что люди не очень хорошо запоминают значения хэшей. В данном случае имя crazy_wozniak относится к нашему контейнеру.
Теперь, поскольку мы отслеживаем /tmp/test на моей локальной машине, если я создам в этом каталоге новый файл, то это должно отразиться в логах контейнера:
Логи Docker демонстрируют, что приложение работает правильно
Вот и всё, теперь ваша программа докеризирована и запущена на вашей машине. Далее нам нужно решить проблему передачи программы другим людым.
Делимся программой
Ваша докеризированная программа может пригодиться вашим коллегам, друзьям, вам в будущем, да и кому угодно в мире, поэтому нам нужно упростить её распространение. Идеальным решением для этого является Docker hub.
Если у вас ещё нет аккаунта, зарегистрируйтесь, а затем выполните логин из cli:
Логинимся в Dockerhub
Далее пометим и запушим только что созданный образ в свой аккаунт.
Добавляем метку и пушим образ
Теперь образ находится в вашем аккаунте docker hub
Чтобы убедиться, что всё работает, попробуем выполнить pull этого образа и использовать в сквозном тестировании всей проделанной нами работы:
Сквозное тестирование нашего образа docker
Весь этот процесс занял всего 30 секунд.
Что дальше?
Надеюсь, мне удалось убедить вас в потрясающей практичности контейнеризации. Docker останется с нами надолго, и чем раньше вы его освоите, тем больше получите преимуществ.
Суть Docker заключается в снижении сложности. В нашем примере это был простой скрипт на Python, но можно использовать этот туториал и для создания образов произвольной сложности с деревьями зависимостей, напоминающими спагетти, но конечного пользователя эти трудности не коснутся.
Источники
На правах рекламы
Вдсина предлагает виртуальные серверы на Linux или Windows. Используем исключительно брендовое оборудование, лучшую в своём роде панель управления серверами собственной разработки и одни из лучших дата-центров в России и ЕС. Поспешите заказать!
Реализуем преобразования кода на Python
Сегодня мы предлагаем вам перевод статьи, затрагивающей не самую обсуждаемую тему: компиляцию кода в Python, а именно: работу с абстрактным синтаксическим деревом (AST) и байт-кодом. Притом, что Python является интерпретируемым языком, такие возможности в нем чрезвычайно важны с точки зрения оптимизации. О них мы сегодня и поговорим.
Вы когда-нибудь задумывались, как именно компилятор оптимизирует ваш код, чтобы он работал быстрее? Хотите узнать, что такое абстрактное синтаксическое дерево (AST) и для чего оно может использоваться?
В этой обзорной статье рассказано, как код Python преобразуется в древовидную форму (AST). Соорудив AST вашей программы, вы сможете перейти к поиску возможностей оптимизации и преобразования вашего кода. Однако учтите, что оптимизация программ Python нетривиальными способами исключительно сложна.
Код программы как дерево
Как компьютеру убедиться, что он вычисляет выражения из вашего кода в правильном порядке?
Для этого он сначала переделывает код вашей программы в древовидную структуру под названием AST.
В Python применяются стандартные правила математической нотации (сначала умножение, затем сложение). Чтобы ничего не перепутать с приоритетом операторов, в Python сначала строится именно такое дерево, как на предыдущей картинке. Общая операция – это сложение (у корня дерева), и, тогда как левая часть этой суммы представляет собой обычное число, справа мы имеем произведение. Результирующая структура данных выглядит так:
BinOp означает Binary Operation (Бинарная операция) и указывает на то, что в таких операциях как сложение и умножение – по два операнда. Естественно, никакого сложения у вас не получится, если в правой части выражения не будет правильного значения – поэтому сначала нужно произвести умножение.
Однако вы заметите, что в AST, сгенерированном Python, будут дополнительные узлы и поля, а выводиться оно будет в одну строку, из-за чего на первый взгляд оно кажется сложнее, чем есть на самом деле.
Давайте разобьем его на отдельные узлы, как и в прошлый раз – и заново откроем AST, уже сверху, как часть всего дерева:
Процесс компиляции: оставшаяся часть
Иными словами, процесс компиляции программы, написанной на Python, проходит в два этапа. Сначала программа, полученная на вход, проходит парсинг, и в результате получается абстрактное синтаксическое дерево (AST). Затем компилятор проходит по AST и при этом генерирует байт-код. После чего интерпретатор Python выполняет этот байт-код. Взявшись за оптимизацию, ее можно применить или на уровне AST, или на уровне байт-кода. Обоим этим вариантам свойственны собственные достоинства и недостатки.
Наконец, нужно учитывать, что, хотя, AST в любой реализации Python является общей, процесс трансляции AST в байт-код может отличаться, и в некоторых реализациях Python на промежуточном этапе может генерироваться, скажем, JavaScript, а не байт-код.
Парадигмы из других языков программирования
Преобразование узла внутри AST
Имея AST программы, как преобразовывать отдельные части этого дерева? При помощи удобных встроенных возможностей Python.
Необходимость скопировать поля, описывающие позицию узла в исходном коде, возникает довольно часто. Поэтому в модуле ast есть выделенная функция copy_location как раз для этой цели, и мы можем написать:
Кстати, компилятор CPython уже оптимизирует узлы BinOp так, как показано здесь. Соответствующий код написан на C и приводится в Python/ast_opt.c. Обратите внимание: оптимизатор CPython более универсален и работает не только с числами, как в рассматриваемом нами примере, но с различными типами константных значений.
Проверка узлов в AST
Как убедиться, что сделанные нами преобразования были правильными? Для начала нужно полностью обойти AST и осмотреть всю программу.
Возможно, именно такого поведения вы и добивались, делая pi истинной константной, которая заменяется при компиляции и никогда не может быть переприсвоена, то есть, не может получить другое значение. Однако это, определенно, нарушает семантику Python.
Теперь мы используем узел посетитель, похожий на узел-преобразователь, описанный выше. В отличие от преобразователя, посетитель не предназначен для изменения каких-либо узлов, он просто проходит по AST и осматривает узлы (посещает их). Соответственно, визитирующие методы ничего не возвращают.
В нашем случае мы проверяем, ссылается ли узел Name на pi и делает ли что-либо кроме загрузки значения pi (помним о поле контекста ctx ).
Локальные значения в Python
Наш метод, позволяющий определить, не изменил ли программист значение pi, получился довольно грубым. Тем не менее, компилятор Python действует весьма схожим образом, когда определяет, какие имена в области видимости функции соответствуют локальным переменным. Если переменная изменяется где-либо в области видимости функции (и явно не сделана глобальной, например, при помощи инструкции global), то эта переменная считается локальной во всей области видимости функции.
Следующий пример отлично выполнится и без четвертой строки. Но, хотя x = 0 в четвертой строке никогда и не выполняется, это все равно считается присваиванием к x и, следовательно, x становится локальной переменной в масштабах всей функции, и даже в строке 3. Вот почему Python будет ругаться, что переменная x в третьей строке еще не имеет значения.
Если вас интересуют подробности, как именно здесь работает Python, посмотрите Python/symtable.c.
Заключение
В Python, как и в большинстве языков программирования, конкретная программа не исполняется непосредственно из исходного кода. На самом деле, трансляция исходного кода происходит в два этапа: из него сначала делается абстрактное синтаксическое дерево (AST), а затем байт-код для стековой виртуальной машины. В Python также предоставляется ряд очень приятных возможностей для анализа и даже преобразования AST любой конкретной программы Python, после чего измененное AST можно компилировать и выполнять. Таким образом, мы можем с легкостью внедрить наши собственные оптимизации.
Разумеется, немало деталей я здесь просто опустил. Чтобы убедиться, что ваша оптимизация корректно сработает во всех возможных случаях и обстоятельствах – дело весьма нетривиальное. Однако цель этой статьи – не рассказать вам об оптимизации, готовой для использования в продакшене, а дать базовое представление о том, как Python анализирует ваш программный код, чтобы вы научились его правильно преобразовывать, а затем и оптимизировать.
Способ 1
Если у вас установлена более высокая версия Python, попробуйте использовать Способ 2 (ниже)
Прежде всего на нужно создать виртуальное окружение для Python3.4. В этом примере мы назовем myenv, Вы можете выбрать любое другое имя, но не забывайте сделать соответствующие изменения.
На терминале наберите следующие команды:
В командной строке появится префикс myenv, а это значит, что виртуальное окружение с именем myenv загружено. Все команды Python теперь будет использовать новое виртуальное окружение.
Теперь давайте установим py2exe (https://pypi.python.org/pypi/py2exe
HEAD=dobj) в нашем виртуальном окружении:
И, наконец, чтобы создать единый EXE-файл, в нашем виртуальном окружении выполняем команду:
(замените hello.py на имя вашего скрипта. Если скрипт находится в другой папке, то нужно использовать полный путь к вашему сценарию, например, C:\Projects\Python\ hello.py). Это создаст папку DIST, которая содержит исполняемый файл. Для быстрого доступа к нему, наберите в терминале:
Вы увидите путь к папке, где находится EXE-файл.
Примечание: При выполнении, откроется окно и исчезают так же быстро, как и появилось.
Это происходит потому, что операционная система автоматически закрывает терминал, в котором консольная программа закончена.
Для того, чтобы изменить эту ситуацию, можно добавить строчку
в конце файла Python. Интерпретатор будет ждать ввода пользователя, а окно будет оставаться открытым, пока пользователь не нажимает клавишу ввода.
Вы можете подробно изучить использование py2exe в документации на странице модуля: https://pypi.python.org/pypi/py2exe
Выход из виртуального окружения производится командой
Способ 2
Через командную строку Windows устанавливаем pyinstaller:
В командной строке переходим в папку, где находится файл
Затем в командной строке набираем команду
Вместо exapmle.py используем имя файла, из которого нужно создать exe файл.
Через пару минут все готово! Скоркее всего, exe файл будет находится во созданной подпапке dist
ERROR: Command errored out with exit status 1: ‘d:\pythoninstalling\python.exe’ ‘C:\Users\Компьютер\AppData\Roaming\Python\Python38\site-packages\pip_vendor\pep517_in_process.py’ prepare_metadata_for_build_wheel ‘C:\Users\4D2B
1\AppData\Local\Temp\tmpr7hey5ho’ Check the logs for full command output.
2 ответа 2
Если есть проблема со сменой версии на ниже, вот руководство:
Узнаём расположение нашего Python (в пуске ищем папку Python, кликаем ПКМ по ней, нажимаем на пункт «Расположение файла», дальше, если видим ярлыки вместо папок и файлов питона, нажимаем ПКМ по ярлыку, и жмём «Расположение файла», так мы оказались в директории питона), переходим в папку Scripts, копируем путь к ней. Далее с помощью поиска, пишем ключевые слова: переменных сред, нажимаем на Изменение системных переменных среды. Нажимаем на кнопку «Переменные среды. «. Выбираем переменную «PATH» и нажимаем «Изменить». Нажимаем на кнопку «Создать» и вставляем путь к папке Scripts, скопированный нами ранее. Сохраняем это всё, выходим из окон. Перезапускаем cmd, вуаля!
Позаимствованное видео по заданному вопросу:
Пару команд для корректной работы:
Для того чтобы вся операция произошла корректно, нужно в начале перейти в директорию с файлом, из которого Вы хотите сделать .exe. Всё это нужно делать в консоли Windows, как и описано в видео.
Есть пару команд под нужды пользователя:
В этом варианте мы скомпилировали программу в единую, но pyinstaller подставил свою иконку программе и чтобы это изменить нужно добавить к команде выше некоторые корректировки:
Таким образом мы компилируем программу с выбранной нами иконкой.
Используем PyInstaller для создания exe-файла игры на Pygame
Я, как и многие новички в создании игр, столкнулся с проблемой как поделиться готовым проектом с друзьями, у которых не установлен Python.
На недостаток обучалок по созданию игр на Pygame не пожалуешься, но мне не удалось найти подробной инструкции как собрать единый exe-файл, для запуска которого не требуется держать рядом папку с изображениями и игровыми звуками.
Из множества библиотек, собирающих проекты в exe, выбрал PyInstaller. Его оказалось достаточно, чтобы справиться с задачей. Опишу все пошагово (для Windows).
Установка PyInstaller
В командной строке пишем:
Создание spec-файла (файла спецификации)
Pyinstaller создает приложение, выполняя содержимое файла спецификации.
Чтобы создать spec-файл, через командную строку в папке с проектом набираем:
Получаем файл mygame.spec
Теперь нужно правильно настроить spec-файл. Открываем spec-файл в текстовом редакторе.
В качестве первого атрибута для объекта класса Analysis передается имя py-файла, который нужно скомпилировать.
Атрибут pathex отвечает за путь к папке проекта.
В списке datas указываются файлы, которые нужно загрузить для работы приложения (изображения, музыка/звуки, шрифты). Datas — это список кортежей. Каждый кортеж имеет два элемента строкового типа:
Редактирование путей к файлам в коде
В коде до загрузки файлов необходимо добавить функцию, которая позволит программе найти необходимые для работы файлы независимо от своего расположения (подсмотрено тут).
При запуске приложения PyInstaller распаковывает данные во временную папку и сохраняет путь к ней в переменной среды _MEIPASS.
Функция resource_path проверяет создана ли временная папка, и если да, то возвращает путь к ней для дальнейшей загрузки файлов. В противном случае (например, если запустить код через интерпретатор) функция вернет тот путь, который в неё передали (то есть путь к папке проекта с игрой).
Чтобы получить путь к файлу
При этом, если файл вынесен в отдельную папку проекта, то и во временной папке нужно создавать соответствующий подкаталог (см. редактирование параметра datas).
Далее загружаем файл:
С музыкой и шрифтами аналогично.
В командной строке вводим:
Готово! Exe-файл находится в папке dist.
Если в коде вашей игры в качестве функций выхода используются quit() или exit(), то скомпилированное приложение работать не будет.
Эти функции включены, чтобы новичкам было проще ориентироваться в коде, и предназначены только для использования в интерпретаторе. На самом деле для их корректной работы требуется загрузить модуль site.