MicroPython:Основы/Язык MicroPython и его реализация/Дистрибутивы, управление пакетами и развертка приложений: различия между версиями

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
(Новая страница: «{{MicroPython/Панель перехода}} {{Перевод от Сubewriter}} {{Myagkij-редактор}} <syntaxhighlight lang="python" enclose="div"> =...»)
 
Нет описания правки
 
(не показаны 4 промежуточные версии 1 участника)
Строка 3: Строка 3:
{{Myagkij-редактор}}
{{Myagkij-редактор}}


=Дистрибутивы, управление пакетами и развертка приложений<ref>[http://docs.micropython.org/en/latest/reference/packages.html docs.micropython.org - Distribution packages, package management, and deploying applications]</ref>=


Как и в ''«старшем»'' [[Python]], в [[MicroPython]] можно создавать ''«сторонние»'' пакеты, распространять их и легко устанавливать на платформу каждого пользователя. Здесь рассказывается, как все это делать, но подразумевается, что у вас уже есть некоторые знания о работе с пакетами в [[Python]].


<syntaxhighlight lang="python" enclose="div">
Процесс создания и использования пакетов включает в себя следующие этапы:
# Модули и пакеты [[Python]] преобразовываются в дистрибутивные пакеты-архивы и публикуются в каталоге [[Python Package Index]] (''«каталог пакетов Python»'') или [[PyPI]].
# Для установки дистрибутивного пакета (дистрибутива) в [[MicroPython-порт]], у которого есть средства для выхода в сеть (например, [[Unix]]), можно воспользоваться менеджером пакетов [[upip]].
# Для установки дистрибутива в [[MicroPython-порт]], у которого нет средства для выхода в сеть, можно сначала подготовить ''«установочный образ»'' на [[Unix-порт]]е, а затем с помощью подходящих коммуникационных средств передать его на устройство.
# Если речь об устройства с ограниченной памятью, установочный образ можно заморозить как [[байт-код]] в прошивку [[MicroPython]], что позволит минимизировать требования к памяти.
 
Ниже все эти шаги описаны более подробно.
 
== Распространение пакетов ==
 
Модули и пакеты [[Python]] можно упаковать в архивы, которые затем можно передавать из одной системы в другую, сохранять в общеизвестном хранилище ([[PyPl]]) и при необходимости оттуда их скачивать (чтобы потом установить). Эти архивы также называются ''«дистрибутивами»'' (что отличает их от Python-пакетов, предназначенных для организации исходного кода [[Python]]).
 
Форматом для дистрибутива [[MicroPython]] является широко известный ''«tar.gz»'', но с некоторыми адаптациями. В компрессоре [[GZIP]] для работы с [[TAR-архив]]ами используется внешняя утилита, которая по умолчанию использует размер словаря в ''32 Кб'', и это значит, что при распаковке сжатого потокового объекта понадобятся смежные участки памяти общим размером в ''32 Кб''. На устройствах с ограниченной памятью такой вариант может быть неприемлем, потому что вся их память может быть меньше, чем эти ''32 Кб'', но даже если больше, из-за фрагментации такой большой блок смежных участков памяти, возможно, найти будет трудно. Для решения этой проблемы в дистрибутивах [[MicroPython]] используется [[GZIP-сжатие]] с размером словаря в ''4 Кб'', что создает приемлемый компромисс между возможностью более-менее сжать данные и возможностью распаковать их даже на самых маленьких устройствах.
 
Помимо маленького размера словаря при сжатии, в дистрибутивах [[MicroPython]] есть и другие оптимизационные функции – вроде удаления из архива всех файлов, не используемых в процессе установки. В частности, во время установки менеджер пакетов [[upip]] не выполняет файл ''«setup.py»'' (см. выше), и поэтому этот файл в архив добавлен не будет.
 
В то же время эти оптимизационные меры делают дистрибутивы [[MicroPython]] не совместимыми с пакетным менеджером [[CPython]] – [[pip]]. Но это не такая уж большая проблема, потому что пакеты можно установить с помощью [[upip]], а потом использовать с помощью [[CPython]] (если они совместимы). С другой стороны, большинство пакетов [[CPython]] по разным причинам не совместимы с [[MicroPython]], в первую очередь – потому что полагаются на функции, которые не реализованы в [[MicroPython]].
 
Итак, если вкратце, дистрибутивы-архивы [[MicroPython]] хорошо оптимизированы под целевые платформы [[MicroPython]], коими являются устройства с ограниченными ресурсами.
 
== Менеджер пакетов upip ==
 
Дистрибутивы [[MicroPython]] необходимо устанавливать с помощью менеджера пакетов [[upip]]. Это [[Python]]-приложение, которое обычно распространяется (в виде замороженного [[байт-код]]а) вместе с портами [[MicroPython]], имеющими средства для работы с сетью. Менеджер пакетов [[upip]] доступен как минимум на порте [[MicroPython]] [[Unix]].
 
На любом [[MicroPython-порт]]е, где есть [[upip]], доступ к нему можно получить следующим образом:
 
<syntaxhighlight lang="python">
import upip
upip.help()
upip.install(package_or_package_list, [path])
</syntaxhighlight>
 
Здесь ''package_or_package_list'' – это название дистрибутива или список с названиями дистрибутивов, которые нужно установить. В опциональном параметре ''path'' указывается место в файловой системе, куда его/их надо установить. По умолчанию установка выполняется в стандартную директорию с библиотеками (см. ниже).
 
Ниже – пример установки пакета и его последующего использования:
 
<syntaxhighlight lang="python">
>>> import upip
>>> upip.install("micropython-pystone_lowmem")
[...]
>>> import pystone_lowmem
>>> pystone_lowmem.main()
</syntaxhighlight>
 
Обратите внимание, что названия [[Python-пакет]]а и дистрибутива, как правило, совпадать не должны, и зачастую действительно не совпадают. Дело в том, что [[PyPI]] – это центральный репозиторий пакетов для всего разнообразия реализаций и версий Python, и поэтому ваш дистрибутив, возможно, надо будет поместить в пространство имен конкретной реализации. К примеру, названия всех пакетов в ''«micropython-lib»'' следуют следующему правилу: если модуль или пакет [[Python]] назван foo, то его дистрибутив будет называться ''micropython-foo''.
 
В портах, где прошивка [[MicroPython]] запускается из командной оболочки [[ОС]] (вроде [[Unix-порт]]а), [[upip]] можно запустить (и обычно именно так он и запускается) именно оттуда, а не из [[MicroPython]]’овского терминала [[REPL]]. Вот команды, соответствующие фрагменту выше:
 
<syntaxhighlight lang="python">
micropython -m upip -h
micropython -m upip install [-p <path>] <packages>...
micropython -m upip install micropython-pystone_lowmem
</syntaxhighlight>
 
== Кросс-установка пакетов ==
 
Для [[MicroPython-порт]]ов, не имеющих средства для работы с сетью, рекомендуется ''«кросс-установить»'' их в ''«установочный образ»'' при помощи порта [[MicroPython]] [[Unix]], а затем передать этот образ на устройство с помощью подходящих коммуникационных средств.
 
Для установки в установочный образ в [[upip]] нужно воспользоваться переключателем ''-p'':
 
<syntaxhighlight lang="python">
micropython -m upip install -p install_dir micropython-pystone_lowmem
</syntaxhighlight>
 
После того, как эта команда будет выполнена, содержимое пакета (и всех зависимых пакетов) можно будет найти в поддиректории ''install_dir/''. Вам нужно будет отправить содержимое этой директории (без префикса ''install_dir/'') на необходимое место в устройстве – туда, где его сможет найти [[Python-оператор]] [[import]] (см. раздел «[http://wikihandbk.com/wiki/MicroPython:%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B/%D0%AF%D0%B7%D1%8B%D0%BA_MicroPython_%D0%B8_%D0%B5%D0%B3%D0%BE_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F/%D0%94%D0%B8%D1%81%D1%82%D1%80%D0%B8%D0%B1%D1%83%D1%82%D0%B8%D0%B2%D1%8B,_%D1%83%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0%D0%BC%D0%B8_%D0%B8_%D1%80%D0%B0%D0%B7%D0%B2%D0%B5%D1%80%D1%82%D0%BA%D0%B0_%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9#.D0.9C.D0.B5.D0.BD.D0.B5.D0.B4.D0.B6.D0.B5.D1.80_.D0.BF.D0.B0.D0.BA.D0.B5.D1.82.D0.BE.D0.B2_upip Менеджер пакетов upip]» выше).
 
== Кросс-установка пакетов с заморозкой ==
 
Для устройств с ограниченной памятью вариант установки в предыдущем разделе не слишком эффективен с точки зрения использования памяти, потому что в нем пакеты устанавливаются в виде исходного кода, поэтому при каждом импорте их надо будет компилировать в [[байт-код]]. Эта компиляция требует [[RAM-памяти]], и получившийся [[байт-код]] тоже будет храниться в RAM-памяти, что уменьшит количество памяти для хранения данных приложения. Более того, процесс установки выше требует наличия файловой системы на устройстве, а у большинства устройств с ограниченной памятью ее может даже не быть.
 
Заморозка байт-кода – это процесс, позволяющий решить все описанные выше проблемы, потому что:
* Исходный код предкомпилируется в байт-код и будет сохранен в таком виде
* Байт-код хранится в ROM-, а не в RAM-памяти
* Замороженным пакетам файловая система не нужна
 
Использование замороженного байт-кода требует создания прошивки MicroPython-порта из исходного кода на [[Си]]. Соответственно, процесс будет таким:
# Следуйте инструкциям для своей платформы по настройке тулчейна и сборке порта. К примеру, инструкции для [[ESP8266-порт]]а находятся в ''«ports/esp8266/README.md»''. Перед тем, как приступать к следующим шагам, убедитесь, что сборка порта и установка получившейся прошивки прошли успешно.
# Соберите порт [[MicroPython]] [[Unix]], и убедитесь, что он находится в ''PATH'', а затем выполните ''micropython''.
# Переключитесь на директорию порта (например, у [[ESP8266]] это ''«ports/esp8266/»'').
# Запустите ''make clean-frozen''. Это удалит все предыдущие модули, которые были установлены для заморозки (если вы хотите добавить новые модули, этот шаг надо пропустить, чтобы не начинать с нуля).
# Запустите ''micropython -m upip install -p modules <пакеты>...'', чтобы установить пакеты, которые вы хотите заморозить.
# Запустите ''make clean''.
# Запустите ''make''.
 
После этого вы должны получить прошивку, внутри которой будут модули в виде замороженного [[байт-код]]а, которую можно устанавливать как обычно.
Пара примечаний:
# Шаг 5 в инструкции выше подразумевает, что используемый дистрибутив есть в каталоге [[PyPI]]. Если его там нет, вам надо будет вручную скопировать файлы исходного кода [[Python]] в поддиректорию ''«modules/»'' в директории порта. (Учтите, что [[upip]] не поддерживает установку из репозиториев системы управления версиями).
# У прошивки для ''«голого железа»'' обычно имеются ограничения по размеру, поэтому слишком большое количество замороженных модулей может ее переполнить. Обычно в таком случае выдается ошибка связывания. Но иногда сгенерированный образ запустить не получается – это типовой баг, о нем нужно сообщить разработчикам, чтобы они разобрались в чем дело. Если вы столкнулись с такой проблемой, первым делом можно попробовать уменьшить количество замороженных модулей в прошивке.
 
== Создание дистрибутивов ==
 
Дистрибутивы для [[MicroPython]] создаются также, как и для [[CPython]] и любой другой реализации [[Python]] (более подробно см. в ссылках в конце статьи). Вместо ''distutils'' необходимо использовать ''setuptools'', потому что в ''distutils'' не поддерживаются зависимости и другие функции. Для упаковки используется формат ''sdist'' (от англ. ''«source distribution»''). Постобработка, о которой рассказывалось выше (и предобработка, о которой будет рассказано в следующем разделе) выполняется при помощи модифицированной ''setuptools''-команды ''sdist''. То есть упаковка будет работать, как и у стандартного ''setuptools'', но пользователю лишь нужно переопределить команду ''sdist'', вставив в ''setup()'' вот такой аргумент:
 
<syntaxhighlight lang="python">
from setuptools import setup
import sdist_upip
 
setup(
    ...,
    cmdclass={'sdist': sdist_upip.sdist}
)
</syntaxhighlight>
 
Модуль ''sdist_upip.py'' из фрагмента выше можно найти в [https://github.com/micropython/micropython-lib/blob/master/sdist_upip.py micropython-lib].
 
== Ресурсы приложения ==
 
Помимо исходного кода, в готовом приложении также часто содержатся файлы данных: шаблоны веб-страниц, изображения и т.д. Понятно, как работать с ними, если приложение установлено вручную – вы просто помещаете эти данные в какое-то место файловой системы, а затем используете обычные функции для доступа к данным.
 
Но все меняется, когда приложение устанавливается из пакета. Это более продвинутый, простой и гибкий способ установки, но в этом случае вам также нужно воспользоваться более продвинутым методом для доступа к файлам данных. Он заключается в том, чтобы относиться к этим файлам данных как к «ресурсам» и сделать парочку дополнительных манипуляций.
 
В Python доступ к ресурсам поддерживается с помощью модуля ''pkg_resources'' из библиотеки ''«setuptools»''. [[MicroPython]] тоже частично поддерживает функционал этого модуля – в частности, за это отвечает функция ''pkg_resources.resource_stream(пакет, ресурс)''. Идея в том, что приложение может вызвать эту функцию и задать в ней аргументом идентификатор нужного ресурса – это будет относительный путь к файлу данных внутри заданного пакета (как правило, пакета приложения высокого уровня). Она вернет потоковый объект, который можно использовать для доступа к содержимому ресурсов. Таким образом, функция ''resource_stream()'' эмулирует интерфейс стандартной функции ''open()''.
 
Если пакет установлен в файловую систему, то ''resourse_stream()'' будет использовать файловые операции. Но эта функция может работать и без файловой системы – например, если пакет заморожен в виде [[байт-код]]а. Это, однако, требует дополнительного этапа при упаковке приложения – создания ''«ресурсного Python-модуля»''.
 
Идея этого модуля в том, чтобы преобразовать двоичные данные в [[Python-объект]] [[bytes]], а затем поместить его в словарь, данные в котором будут упорядочены по названиям ресурсов. Это преобразование выполняется автоматически при помощи переопределенной команды ''sdist'', описанной в предыдущем разделе.
 
Теперь давайте рассмотрим всё это с помощью наглядного примера. Допустим, ваше приложение имеет следующую структуру:
 
<syntaxhighlight lang="python">
my_app/
    __main__.py
    utils.py
    data/
        page.html
        image.png
</syntaxhighlight>
 
Файлы ''«__main__.py»'' и ''«utils.py»'' получают доступ к ресурсам с помощью вот этих функций:
 
<syntaxhighlight lang="python">
import pkg_resources
 
pkg_resources.resource_stream(__name__, "data/page.html")
pkg_resources.resource_stream(__name__, "data/image.png")
</syntaxhighlight>
 
Вы можете как обычно разрабатывать и делать отладку приложения на порте [[MicroPython]] [[Unix]]. Когда наступит время делать из него дистрибутив, просто воспользуйтесь переопределенной командой ''sdist'' из модуля ''sdist_upip'', как описывалось в разделе выше.
 
Это создаст ресурсный [[Python-модуль]] под названием ''R.py'' на основе файлов, объявленных в файлах ''MANIFEST'' и ''MANIFEST.in'' (любой файл без ''«[[*.py]]»'' будет считаться ресурсом и добавлен в ''R.py'') – перед тем, как приступить к обычным этапам упаковки.
 
Если подготовить приложение таким образом, оно будет работать и в виде замороженного [[байт-код]]а, и будучи установленным в файловую систему.
 
Чтобы начать отладку создания ''R.py'', запустите следующее:
 
<syntaxhighlight lang="python">
python3 setup.py sdist --manifest-only
</syntaxhighlight>
 
В качестве альтернативы можно воспользоваться скриптом ''«tools/mpy_bin2res.py»'' из дистрибутива [[MicroPython]] – в этом случае вам нужно будет также указать пути ко всем файлам ресурсов:
 
<syntaxhighlight lang="python">
mpy_bin2res.py data/page.html data/image.png
</syntaxhighlight>
 
==Ссылки==
 
* [https://packaging.python.org/ Руководство по упаковке в Python]
* [https://setuptools.readthedocs.io/en/latest/ Документация поsetuptools]
* [https://docs.python.org/3/library/distutils.html Документация по distutils]


=См.также=
=См.также=
{{ads}}


=Внешние ссылки=
=Внешние ссылки=


<references />
<references />

Текущая версия от 18:17, 14 мая 2023

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Дистрибутивы, управление пакетами и развертка приложений[1]

Как и в «старшем» Python, в MicroPython можно создавать «сторонние» пакеты, распространять их и легко устанавливать на платформу каждого пользователя. Здесь рассказывается, как все это делать, но подразумевается, что у вас уже есть некоторые знания о работе с пакетами в Python.

Процесс создания и использования пакетов включает в себя следующие этапы:

  1. Модули и пакеты Python преобразовываются в дистрибутивные пакеты-архивы и публикуются в каталоге Python Package Index («каталог пакетов Python») или PyPI.
  2. Для установки дистрибутивного пакета (дистрибутива) в MicroPython-порт, у которого есть средства для выхода в сеть (например, Unix), можно воспользоваться менеджером пакетов upip.
  3. Для установки дистрибутива в MicroPython-порт, у которого нет средства для выхода в сеть, можно сначала подготовить «установочный образ» на Unix-порте, а затем с помощью подходящих коммуникационных средств передать его на устройство.
  4. Если речь об устройства с ограниченной памятью, установочный образ можно заморозить как байт-код в прошивку MicroPython, что позволит минимизировать требования к памяти.

Ниже все эти шаги описаны более подробно.

Распространение пакетов

Модули и пакеты Python можно упаковать в архивы, которые затем можно передавать из одной системы в другую, сохранять в общеизвестном хранилище (PyPl) и при необходимости оттуда их скачивать (чтобы потом установить). Эти архивы также называются «дистрибутивами» (что отличает их от Python-пакетов, предназначенных для организации исходного кода Python).

Форматом для дистрибутива MicroPython является широко известный «tar.gz», но с некоторыми адаптациями. В компрессоре GZIP для работы с TAR-архивами используется внешняя утилита, которая по умолчанию использует размер словаря в 32 Кб, и это значит, что при распаковке сжатого потокового объекта понадобятся смежные участки памяти общим размером в 32 Кб. На устройствах с ограниченной памятью такой вариант может быть неприемлем, потому что вся их память может быть меньше, чем эти 32 Кб, но даже если больше, из-за фрагментации такой большой блок смежных участков памяти, возможно, найти будет трудно. Для решения этой проблемы в дистрибутивах MicroPython используется GZIP-сжатие с размером словаря в 4 Кб, что создает приемлемый компромисс между возможностью более-менее сжать данные и возможностью распаковать их даже на самых маленьких устройствах.

Помимо маленького размера словаря при сжатии, в дистрибутивах MicroPython есть и другие оптимизационные функции – вроде удаления из архива всех файлов, не используемых в процессе установки. В частности, во время установки менеджер пакетов upip не выполняет файл «setup.py» (см. выше), и поэтому этот файл в архив добавлен не будет.

В то же время эти оптимизационные меры делают дистрибутивы MicroPython не совместимыми с пакетным менеджером CPythonpip. Но это не такая уж большая проблема, потому что пакеты можно установить с помощью upip, а потом использовать с помощью CPython (если они совместимы). С другой стороны, большинство пакетов CPython по разным причинам не совместимы с MicroPython, в первую очередь – потому что полагаются на функции, которые не реализованы в MicroPython.

Итак, если вкратце, дистрибутивы-архивы MicroPython хорошо оптимизированы под целевые платформы MicroPython, коими являются устройства с ограниченными ресурсами.

Менеджер пакетов upip

Дистрибутивы MicroPython необходимо устанавливать с помощью менеджера пакетов upip. Это Python-приложение, которое обычно распространяется (в виде замороженного байт-кода) вместе с портами MicroPython, имеющими средства для работы с сетью. Менеджер пакетов upip доступен как минимум на порте MicroPython Unix.

На любом MicroPython-порте, где есть upip, доступ к нему можно получить следующим образом:

import upip
upip.help()
upip.install(package_or_package_list, [path])

Здесь package_or_package_list – это название дистрибутива или список с названиями дистрибутивов, которые нужно установить. В опциональном параметре path указывается место в файловой системе, куда его/их надо установить. По умолчанию установка выполняется в стандартную директорию с библиотеками (см. ниже).

Ниже – пример установки пакета и его последующего использования:

>>> import upip
>>> upip.install("micropython-pystone_lowmem")
[...]
>>> import pystone_lowmem
>>> pystone_lowmem.main()

Обратите внимание, что названия Python-пакета и дистрибутива, как правило, совпадать не должны, и зачастую действительно не совпадают. Дело в том, что PyPI – это центральный репозиторий пакетов для всего разнообразия реализаций и версий Python, и поэтому ваш дистрибутив, возможно, надо будет поместить в пространство имен конкретной реализации. К примеру, названия всех пакетов в «micropython-lib» следуют следующему правилу: если модуль или пакет Python назван foo, то его дистрибутив будет называться micropython-foo.

В портах, где прошивка MicroPython запускается из командной оболочки ОС (вроде Unix-порта), upip можно запустить (и обычно именно так он и запускается) именно оттуда, а не из MicroPython’овского терминала REPL. Вот команды, соответствующие фрагменту выше:

micropython -m upip -h
micropython -m upip install [-p <path>] <packages>...
micropython -m upip install micropython-pystone_lowmem

Кросс-установка пакетов

Для MicroPython-портов, не имеющих средства для работы с сетью, рекомендуется «кросс-установить» их в «установочный образ» при помощи порта MicroPython Unix, а затем передать этот образ на устройство с помощью подходящих коммуникационных средств.

Для установки в установочный образ в upip нужно воспользоваться переключателем -p:

micropython -m upip install -p install_dir micropython-pystone_lowmem

После того, как эта команда будет выполнена, содержимое пакета (и всех зависимых пакетов) можно будет найти в поддиректории install_dir/. Вам нужно будет отправить содержимое этой директории (без префикса install_dir/) на необходимое место в устройстве – туда, где его сможет найти Python-оператор import (см. раздел «Менеджер пакетов upip» выше).

Кросс-установка пакетов с заморозкой

Для устройств с ограниченной памятью вариант установки в предыдущем разделе не слишком эффективен с точки зрения использования памяти, потому что в нем пакеты устанавливаются в виде исходного кода, поэтому при каждом импорте их надо будет компилировать в байт-код. Эта компиляция требует RAM-памяти, и получившийся байт-код тоже будет храниться в RAM-памяти, что уменьшит количество памяти для хранения данных приложения. Более того, процесс установки выше требует наличия файловой системы на устройстве, а у большинства устройств с ограниченной памятью ее может даже не быть.

Заморозка байт-кода – это процесс, позволяющий решить все описанные выше проблемы, потому что:

  • Исходный код предкомпилируется в байт-код и будет сохранен в таком виде
  • Байт-код хранится в ROM-, а не в RAM-памяти
  • Замороженным пакетам файловая система не нужна

Использование замороженного байт-кода требует создания прошивки MicroPython-порта из исходного кода на Си. Соответственно, процесс будет таким:

  1. Следуйте инструкциям для своей платформы по настройке тулчейна и сборке порта. К примеру, инструкции для ESP8266-порта находятся в «ports/esp8266/README.md». Перед тем, как приступать к следующим шагам, убедитесь, что сборка порта и установка получившейся прошивки прошли успешно.
  2. Соберите порт MicroPython Unix, и убедитесь, что он находится в PATH, а затем выполните micropython.
  3. Переключитесь на директорию порта (например, у ESP8266 это «ports/esp8266/»).
  4. Запустите make clean-frozen. Это удалит все предыдущие модули, которые были установлены для заморозки (если вы хотите добавить новые модули, этот шаг надо пропустить, чтобы не начинать с нуля).
  5. Запустите micropython -m upip install -p modules <пакеты>..., чтобы установить пакеты, которые вы хотите заморозить.
  6. Запустите make clean.
  7. Запустите make.

После этого вы должны получить прошивку, внутри которой будут модули в виде замороженного байт-кода, которую можно устанавливать как обычно. Пара примечаний:

  1. Шаг 5 в инструкции выше подразумевает, что используемый дистрибутив есть в каталоге PyPI. Если его там нет, вам надо будет вручную скопировать файлы исходного кода Python в поддиректорию «modules/» в директории порта. (Учтите, что upip не поддерживает установку из репозиториев системы управления версиями).
  2. У прошивки для «голого железа» обычно имеются ограничения по размеру, поэтому слишком большое количество замороженных модулей может ее переполнить. Обычно в таком случае выдается ошибка связывания. Но иногда сгенерированный образ запустить не получается – это типовой баг, о нем нужно сообщить разработчикам, чтобы они разобрались в чем дело. Если вы столкнулись с такой проблемой, первым делом можно попробовать уменьшить количество замороженных модулей в прошивке.

Создание дистрибутивов

Дистрибутивы для MicroPython создаются также, как и для CPython и любой другой реализации Python (более подробно см. в ссылках в конце статьи). Вместо distutils необходимо использовать setuptools, потому что в distutils не поддерживаются зависимости и другие функции. Для упаковки используется формат sdist (от англ. «source distribution»). Постобработка, о которой рассказывалось выше (и предобработка, о которой будет рассказано в следующем разделе) выполняется при помощи модифицированной setuptools-команды sdist. То есть упаковка будет работать, как и у стандартного setuptools, но пользователю лишь нужно переопределить команду sdist, вставив в setup() вот такой аргумент:

from setuptools import setup
import sdist_upip

setup(
    ...,
    cmdclass={'sdist': sdist_upip.sdist}
)

Модуль sdist_upip.py из фрагмента выше можно найти в micropython-lib.

Ресурсы приложения

Помимо исходного кода, в готовом приложении также часто содержатся файлы данных: шаблоны веб-страниц, изображения и т.д. Понятно, как работать с ними, если приложение установлено вручную – вы просто помещаете эти данные в какое-то место файловой системы, а затем используете обычные функции для доступа к данным.

Но все меняется, когда приложение устанавливается из пакета. Это более продвинутый, простой и гибкий способ установки, но в этом случае вам также нужно воспользоваться более продвинутым методом для доступа к файлам данных. Он заключается в том, чтобы относиться к этим файлам данных как к «ресурсам» и сделать парочку дополнительных манипуляций.

В Python доступ к ресурсам поддерживается с помощью модуля pkg_resources из библиотеки «setuptools». MicroPython тоже частично поддерживает функционал этого модуля – в частности, за это отвечает функция pkg_resources.resource_stream(пакет, ресурс). Идея в том, что приложение может вызвать эту функцию и задать в ней аргументом идентификатор нужного ресурса – это будет относительный путь к файлу данных внутри заданного пакета (как правило, пакета приложения высокого уровня). Она вернет потоковый объект, который можно использовать для доступа к содержимому ресурсов. Таким образом, функция resource_stream() эмулирует интерфейс стандартной функции open().

Если пакет установлен в файловую систему, то resourse_stream() будет использовать файловые операции. Но эта функция может работать и без файловой системы – например, если пакет заморожен в виде байт-кода. Это, однако, требует дополнительного этапа при упаковке приложения – создания «ресурсного Python-модуля».

Идея этого модуля в том, чтобы преобразовать двоичные данные в Python-объект bytes, а затем поместить его в словарь, данные в котором будут упорядочены по названиям ресурсов. Это преобразование выполняется автоматически при помощи переопределенной команды sdist, описанной в предыдущем разделе.

Теперь давайте рассмотрим всё это с помощью наглядного примера. Допустим, ваше приложение имеет следующую структуру:

my_app/
    __main__.py
    utils.py
    data/
        page.html
        image.png

Файлы «__main__.py» и «utils.py» получают доступ к ресурсам с помощью вот этих функций:

import pkg_resources

pkg_resources.resource_stream(__name__, "data/page.html")
pkg_resources.resource_stream(__name__, "data/image.png")

Вы можете как обычно разрабатывать и делать отладку приложения на порте MicroPython Unix. Когда наступит время делать из него дистрибутив, просто воспользуйтесь переопределенной командой sdist из модуля sdist_upip, как описывалось в разделе выше.

Это создаст ресурсный Python-модуль под названием R.py на основе файлов, объявленных в файлах MANIFEST и MANIFEST.in (любой файл без «*.py» будет считаться ресурсом и добавлен в R.py) – перед тем, как приступить к обычным этапам упаковки.

Если подготовить приложение таким образом, оно будет работать и в виде замороженного байт-кода, и будучи установленным в файловую систему.

Чтобы начать отладку создания R.py, запустите следующее:

python3 setup.py sdist --manifest-only

В качестве альтернативы можно воспользоваться скриптом «tools/mpy_bin2res.py» из дистрибутива MicroPython – в этом случае вам нужно будет также указать пути ко всем файлам ресурсов:

mpy_bin2res.py data/page.html data/image.png

Ссылки

См.также

Внешние ссылки