packages.rst 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. Distribution packages, package management, and deploying applications
  2. =====================================================================
  3. Just as the "big" Python, MicroPython supports creation of "third party"
  4. packages, distributing them, and easily installing them in each user's
  5. environment. This chapter discusses how these actions are achieved.
  6. Some familiarity with Python packaging is recommended.
  7. Overview
  8. --------
  9. Steps below represent a high-level workflow when creating and consuming
  10. packages:
  11. 1. Python modules and packages are turned into distribution package
  12. archives, and published at the Python Package Index (PyPI).
  13. 2. `upip` package manager can be used to install a distribution package
  14. on a `MicroPython port` with networking capabilities (for example,
  15. on the Unix port).
  16. 3. For ports without networking capabilities, an "installation image"
  17. can be prepared on the Unix port, and transferred to a device by
  18. suitable means.
  19. 4. For low-memory ports, the installation image can be frozen as the
  20. bytecode into MicroPython executable, thus minimizing the memory
  21. storage overheads.
  22. The sections below describe this process in details.
  23. Distribution packages
  24. ---------------------
  25. Python modules and packages can be packaged into archives suitable for
  26. transfer between systems, storing at the well-known location (PyPI),
  27. and downloading on demand for deployment. These archives are known as
  28. *distribution packages* (to differentiate them from Python packages
  29. (means to organize Python source code)).
  30. The MicroPython distribution package format is a well-known tar.gz
  31. format, with some adaptations however. The Gzip compressor, used as
  32. an external wrapper for TAR archives, by default uses 32KB dictionary
  33. size, which means that to uncompress a compressed stream, 32KB of
  34. contguous memory needs to be allocated. This requirement may be not
  35. satisfiable on low-memory devices, which may have total memory available
  36. less than that amount, and even if not, a contiguous block like that
  37. may be hard to allocate due to memory fragmentation. To accommodate
  38. these constraints, MicroPython distribution packages use Gzip compression
  39. with the dictionary size of 4K, which should be a suitable compromise
  40. with still achieving some compression while being able to uncompressed
  41. even by the smallest devices.
  42. Besides the small compression dictionary size, MicroPython distribution
  43. packages also have other optimizations, like removing any files from
  44. the archive which aren't used by the installation process. In particular,
  45. `upip` package manager doesn't execute ``setup.py`` during installation
  46. (see below), and thus that file is not included in the archive.
  47. At the same time, these optimizations make MicroPython distribution
  48. packages not compatible with `CPython`'s package manager, ``pip``.
  49. This isn't considered a big problem, because:
  50. 1. Packages can be installed with `upip`, and then can be used with
  51. CPython (if they are compatible with it).
  52. 2. In the other direction, majority of CPython packages would be
  53. incompatible with MicroPython by various reasons, first of all,
  54. the reliance on features not implemented by MicroPython.
  55. Summing up, the MicroPython distribution package archives are highly
  56. optimized for MicroPython's target environments, which are highly
  57. resource constrained devices.
  58. ``upip`` package manager
  59. ------------------------
  60. MicroPython distribution packages are intended to be installed using
  61. the `upip` package manager. `upip` is a Python application which is
  62. usually distributed (as frozen bytecode) with network-enabled
  63. `MicroPython ports <MicroPython port>`. At the very least,
  64. `upip` is available in the `MicroPython Unix port`.
  65. On any `MicroPython port` providing `upip`, it can be accessed as
  66. following::
  67. import upip
  68. upip.help()
  69. upip.install(package_or_package_list, [path])
  70. Where *package_or_package_list* is the name of a distribution
  71. package to install, or a list of such names to install multiple
  72. packages. Optional *path* parameter specifies filesystem
  73. location to install under and defaults to the standard library
  74. location (see below).
  75. An example of installing a specific package and then using it::
  76. >>> import upip
  77. >>> upip.install("micropython-pystone_lowmem")
  78. [...]
  79. >>> import pystone_lowmem
  80. >>> pystone_lowmem.main()
  81. Note that the name of Python package and the name of distribution
  82. package for it in general don't have to match, and oftentimes they
  83. don't. This is because PyPI provides a central package repository
  84. for all different Python implementations and versions, and thus
  85. distribution package names may need to be namespaced for a particular
  86. implementation. For example, all packages from `micropython-lib`
  87. follow this naming convention: for a Python module or package named
  88. ``foo``, the distribution package name is ``micropython-foo``.
  89. For the ports which run MicroPython executable from the OS command
  90. prompts (like the Unix port), `upip` can be (and indeed, usually is)
  91. run from the command line instead of MicroPython's own REPL. The
  92. commands which corresponds to the example above are::
  93. micropython -m upip -h
  94. micropython -m upip install [-p <path>] <packages>...
  95. micropython -m upip install micropython-pystone_lowmem
  96. [TODO: Describe installation path.]
  97. Cross-installing packages
  98. -------------------------
  99. For `MicroPython ports <MicroPython port>` without native networking
  100. capabilities, the recommend process is "cross-installing" them into a
  101. "directory image" using the `MicroPython Unix port`, and then
  102. transferring this image to a device by suitable means.
  103. Installing to a directory image involves using ``-p`` switch to `upip`::
  104. micropython -m upip install -p install_dir micropython-pystone_lowmem
  105. After this command, the package content (and contents of every depenency
  106. packages) will be available in the ``install_dir/`` subdirectory. You
  107. would need to transfer contents of this directory (without the
  108. ``install_dir/`` prefix) to the device, at the suitable location, where
  109. it can be found by the Python ``import`` statement (see discussion of
  110. the `upip` installation path above).
  111. Cross-installing packages with freezing
  112. ---------------------------------------
  113. For the low-memory `MicroPython ports <MicroPython port>`, the process
  114. described in the previous section does not provide the most efficient
  115. resource usage,because the packages are installed in the source form,
  116. so need to be compiled to the bytecome on each import. This compilation
  117. requires RAM, and the resulting bytecode is also stored in RAM, reducing
  118. its amount available for storing application data. Moreover, the process
  119. above requires presence of the filesystem on a device, and the most
  120. resource-constrained devices may not even have it.
  121. The bytecode freezing is a process which resolves all the issues
  122. mentioned above:
  123. * The source code is pre-compiled into bytecode and store as such.
  124. * The bytecode is stored in ROM, not RAM.
  125. * Filesystem is not required for frozen packages.
  126. Using frozen bytecode requires building the executable (firmware)
  127. for a given `MicroPython port` from the C source code. Consequently,
  128. the process is:
  129. 1. Follow the instructions for a particular port on setting up a
  130. toolchain and building the port. For example, for ESP8266 port,
  131. study instructions in ``ports/esp8266/README.md`` and follow them.
  132. Make sure you can build the port and deploy the resulting
  133. executable/firmware successfully before proceeding to the next steps.
  134. 2. Build `MicroPython Unix port` and make sure it is in your PATH and
  135. you can execute ``micropython``.
  136. 3. Change to port's directory (e.g. ``ports/esp8266/`` for ESP8266).
  137. 4. Run ``make clean-frozen``. This step cleans up any previous
  138. modules which were installed for freezing (consequently, you need
  139. to skip this step to add additional modules, instead of starting
  140. from scratch).
  141. 5. Run ``micropython -m upip install -p modules <packages>...`` to
  142. install packages you want to freeze.
  143. 6. Run ``make clean``.
  144. 7. Run ``make``.
  145. After this, you should have the executable/firmware with modules as
  146. the bytecode inside, which you can deploy the usual way.
  147. Few notes:
  148. 1. Step 5 in the sequence above assumes that the distribution package
  149. is available from PyPI. If that is not the case, you would need
  150. to copy Python source files manually to ``modules/`` subdirectory
  151. of the port port directory. (Note that upip does not support
  152. installing from e.g. version control repositories).
  153. 2. The firmware for baremetal devices usually has size restrictions,
  154. so adding too many frozen modules may overflow it. Usually, you
  155. would get a linking error if this happens. However, in some cases,
  156. an image may be produced, which is not runnable on a device. Such
  157. cases are in general bugs, and should be reported and further
  158. investigated. If you face such a situation, as an initial step,
  159. you may want to decrease the amount of frozen modules included.
  160. Creating distribution packages
  161. ------------------------------
  162. Distribution packages for MicroPython are created in the same manner
  163. as for CPython or any other Python implementation, see references at
  164. the end of chapter. Setuptools (instead of distutils) should be used,
  165. because distutils do not support dependencies and other features. "Source
  166. distribution" (``sdist``) format is used for packaging. The post-processing
  167. discussed above, (and pre-processing discussed in the following section)
  168. is achieved by using custom ``sdist`` command for setuptools. Thus, packaging
  169. steps remain the same as for the standard setuptools, the user just
  170. needs to override ``sdist`` command implementation by passing the
  171. appropriate argument to ``setup()`` call::
  172. from setuptools import setup
  173. import sdist_upip
  174. setup(
  175. ...,
  176. cmdclass={'sdist': sdist_upip.sdist}
  177. )
  178. The sdist_upip.py module as referenced above can be found in
  179. `micropython-lib`:
  180. https://github.com/micropython/micropython-lib/blob/master/sdist_upip.py
  181. Application resources
  182. ---------------------
  183. A complete application, besides the source code, oftentimes also consists
  184. of data files, e.g. web page templates, game images, etc. It's clear how
  185. to deal with those when application is installed manually - you just put
  186. those data files in the filesystem at some location and use the normal
  187. file access functions.
  188. The situation is different when deploying applications from packages - this
  189. is more advanced, streamlined and flexible way, but also requires more
  190. advanced approach to accessing data files. This approach is treating
  191. the data files as "resources", and abstracting away access to them.
  192. Python supports resource access using its "setuptools" library, using
  193. ``pkg_resources`` module. MicroPython, following its usual approach,
  194. implements subset of the functionality of that module, specifically
  195. ``pkg_resources.resource_stream(package, resource)`` function.
  196. The idea is that an application calls this function, passing a
  197. resource identifier, which is a relative path to data file within
  198. the specified package (usually top-level application package). It
  199. returns a stream object which can be used to access resource contents.
  200. Thus, the ``resource_stream()`` emulates interface of the standard
  201. `open()` function.
  202. Implementation-wise, ``resource_stream()`` uses file operations
  203. underlyingly, if distribution package is install in the filesystem.
  204. However, it also supports functioning without the underlying filesystem,
  205. e.g. if the package is frozen as the bytecode. This however requires
  206. an extra intermediate step when packaging application - creation of
  207. "Python resource module".
  208. The idea of this module is to convert binary data to a Python bytes
  209. object, and put it into the dictionary, indexed by the resource name.
  210. This conversion is done automatically using overridden ``sdist`` command
  211. described in the previous section.
  212. Let's trace the complete process using the following example. Suppose
  213. your application has the following structure::
  214. my_app/
  215. __main__.py
  216. utils.py
  217. data/
  218. page.html
  219. image.png
  220. ``__main__.py`` and ``utils.py`` should access resources using the
  221. following calls::
  222. import pkg_resources
  223. pkg_resources.resource_stream(__name__, "data/page.html")
  224. pkg_resources.resource_stream(__name__, "data/image.png")
  225. You can develop and debug using the `MicroPython Unix port` as usual.
  226. When time comes to make a distribution package out of it, just use
  227. overridden "sdist" command from sdist_upip.py module as described in
  228. the previous section.
  229. This will create a Python resource module named ``R.py``, based on the
  230. files declared in ``MANIFEST`` or ``MANIFEST.in`` files (any non-``.py``
  231. file will be considered a resource and added to ``R.py``) - before
  232. proceeding with the normal packaging steps.
  233. Prepared like this, your application will work both when deployed to
  234. filesystem and as frozen bytecode.
  235. If you would like to debug ``R.py`` creation, you can run::
  236. python3 setup.py sdist --manifest-only
  237. Alternatively, you can use tools/mpy_bin2res.py script from the
  238. MicroPython distribution, in which can you will need to pass paths
  239. to all resource files::
  240. mpy_bin2res.py data/page.html data/image.png
  241. References
  242. ----------
  243. * Python Packaging User Guide: https://packaging.python.org/
  244. * Setuptools documentation: https://setuptools.readthedocs.io/
  245. * Distutils documentation: https://docs.python.org/3/library/distutils.html