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

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
Нет описания правки
Строка 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]].
Процесс создания и использования пакетов включает в себя следующие этапы:
# Модули и пакеты [[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" enclose="div">
import upip
upip.help()
upip.install(package_or_package_list, [path])
</syntaxhighlight>
Здесь ''package_or_package_list'' – это название дистрибутива или список с названиями дистрибутивов, которые нужно установить. В опциональном параметре ''path'' указывается место в файловой системе, куда его/их надо установить. По умолчанию установка выполняется в стандартную директорию с библиотеками (см. ниже).
Ниже – пример установки пакета и его последующего использования:
<syntaxhighlight lang="python" enclose="div">
>>> 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" enclose="div">
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" enclose="div">
micropython -m upip install -p install_dir micropython-pystone_lowmem
</syntaxhighlight>
После того, как эта команда будет выполнена, содержимое пакета (и всех зависимых пакетов) можно будет найти в поддиректории install_dir/. Вам нужно будет отправить содержимое этой директории (без префикса install_dir/) на необходимое место в устройстве – туда, где его сможет найти Python-оператор import (см. раздел «Менеджер пакетов 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 в инструкции выше подразумевает, что используемый дистрибутив есть в каталоге PyPl. Если его там нет, вам надо будет вручную скопировать файлы исходного кода Python в поддиректорию «modules/» в директории порта. (Учтите, что upip не поддерживает установку из репозиториев системы управления версиями).
# У прошивки для «голого железа» обычно имеются ограничения по размеру, поэтому слишком большое количество замороженных модулей может ее переполнить. Обычно в таком случае выдается ошибка связывания. Но иногда сгенерированный образ запустить не получается – это типовой баг, о нем нужно сообщить разработчикам, чтобы они разобрались в чем дело. Если вы столкнулись с такой проблемой, первым делом можно попробовать уменьшить количество замороженных модулей в прошивке.
== Создание дистрибутивов ==
Дистрибутивы для MicroPython создаются также, как и для CPython и любой другой реализации Python (более подробно см. в ссылках в конце статьи). Вместо distutils необходимо использовать setuptools, потому что в distutils не поддерживаются зависимости и другие функции. Для упаковки используется формат sdist (от англ. «source distribution»). Постобработка, о которой рассказывалось выше (и предобработка, о которой будет рассказано в следующем разделе) выполняется при помощи модифицированной setuptools-команды sdist. То есть упаковка будет работать, как и у стандартного setuptools, но пользователю лишь нужно переопределить команду sdist, вставив в setup() вот такой аргумент:
<syntaxhighlight lang="python" enclose="div">
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" enclose="div">
my_app/
    __main__.py
    utils.py
    data/
        page.html
        image.png
</syntaxhighlight>
Файлы «__main__.py» и «utils.py» получают доступ к ресурсам с помощью вот этих функций:


<syntaxhighlight lang="python" enclose="div">
<syntaxhighlight lang="python" enclose="div">
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" enclose="div">
python3 setup.py sdist --manifest-only
</syntaxhighlight>
В качестве альтернативы можно воспользоваться скриптом «tools/mpy_bin2res.py» из дистрибутива MicroPython – в этом случае вам нужно будет также указать пути ко всем файлам ресурсов:
<syntaxhighlight lang="python" enclose="div">
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]


=См.также=
=См.также=

Версия от 15:34, 1 августа 2020

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


Дистрибутивы, управление пакетами и развертка приложений[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 в инструкции выше подразумевает, что используемый дистрибутив есть в каталоге PyPl. Если его там нет, вам надо будет вручную скопировать файлы исходного кода 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

Ссылки

См.также

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