Soubory manifestu MicroPython¶
Shrnutí¶
MicroPython má funkci, která umožňuje „zmrazit“ (freeze) Python kód přímo do firmwaru jako alternativu k načítání kódu ze souborového systému.
To má následující výhody:
kód je předem zkompilován do bytecode, čímž odpadá nutnost kompilovat zdrojový kód Python při načítání.
bytecode lze spustit přímo z ROM (tj. flash paměti), místo aby byl kopírován do RAM. Podobně se z ROM načítají i veškeré konstantní objekty (řetězce, n-tice atd.). Díky tomu může být pro vaši aplikaci k dispozici výrazně více paměti.
na zařízeních, která nemají souborový systém, je to jediný způsob, jak načíst Python kód.
Během vývoje se zmrazování obecně nedoporučuje, protože výrazně zpomalí váš vývojový cyklus, neboť každá aktualizace bude vyžadovat opětovné nahrání celého firmwaru. Přesto může být užitečné selektivně zmrazit některé zřídka se měnící závislosti (například knihovny třetích stran).
Soubory Python, které se mají zmrazit do firmwaru, se vypisují pomocí „manifestu“, což je soubor Python interpretovaný procesem sestavení. Manifest obvykle napíšete jako součást definice desky, ale můžete také napsat samostatný soubor manifestu a použít jej s existující definicí desky.
Soubory manifestu mohou definovat závislosti na knihovnách z micropython-lib, na souborech Python v souborovém systému a také na jiných souborech manifestu.
Psaní souborů manifestu¶
Soubor manifestu je soubor Python obsahující sérii volání funkcí. Viz dostupné funkce definované níže.
Jakékoli cesty použité v souborech manifestu mohou obsahovat následující proměnné. Všechny se rozkládají na absolutní cesty.
$(MPY_DIR)– cesta k repozitáři micropython.$(MPY_LIB_DIR)– cesta k submodulu micropython-lib. Upřednostněte použitírequire().$(PORT_DIR)– cesta k aktuálnímu portu (např.ports/stm32)$(BOARD_DIR)– cesta k aktuální desce (např.ports/stm32/boards/OPENMV4)
Vlastní soubory manifestu by neměly být umístěny v hlavním repozitáři MicroPython. Měli byste je uchovávat ve verzovacím systému spolu se zbytkem vašeho projektu.
Manifest používaný pro kompilaci firmwaru obvykle bude muset zahrnovat manifest portu, který může obsahovat zmrazené moduly potřebné pro fungování desky. Pokud chcete pouze přidat další moduly k existující desce, zahrňte manifest desky (který následně zahrne manifest portu).
Sestavení s vlastním manifestem¶
Váš manifest lze zadat na příkazové řádce make pomocí:
$ make BOARD=MYBOARD FROZEN_MANIFEST=/path/to/my/project/manifest.py
To platí pro všechny porty, včetně těch založených na CMake (např. rp2), protože obal Makefile to předá do sestavení CMake.
Přidání manifestu k definici desky¶
Pokud máte vlastní definici desky, můžete zařídit, aby automaticky zahrnovala váš vlastní manifest. Na portech založených na make (většina portů) nastavte ve svém mpconfigboard.mk proměnnou FROZEN_MANIFEST.
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
Na portech založených na CMake (např. rp2) místo toho použijte mpconfigboard.cmake
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
Funkce vysoké úrovně¶
Toto jsou funkce, které budete běžně používat. Přidávají kód do sady, která je předkompilována do bytecode a zmrazena do obrazu firmwaru:
moduleapackagezmrazí váš vlastní lokální zdrojový kód — jeden soubor, respektive celý adresář balíčku.requirezmrazí publikovaný balíček (a jeho závislosti) z micropython-lib podle názvu.includevtáhne další manifest, takže se přidají i jeho zmrazené moduly.add_libraryametadatajsou pomocné funkce (registrace dalších cest pro vyhledávání prorequirea deklarace metadat balíčku).
Typický manifest firmwaru nejprve pomocí include zahrne manifest portu nebo desky (aby moduly, které deska potřebuje, zůstaly zmrazené) a poté přidá vlastní řádky module/package/require.
Poznámka: U různých funkcí lze nastavit pojmenovaný argument opt, který řídí úroveň optimalizace použitou křížovým kompilátorem. Viz micropython.opt_level().
- add_library(library, library_path, prepend=False)¶
Zaregistruje cestu k externí pojmenované library.
Použijte toto, když chcete, aby
requirerozlišoval balíčky z jiného adresáře než micropython-lib — například z vaší vlastní kolekce ovladačů nebo z lokální kopie knihovny třetí strany.Cesta library_path bude automaticky prohledána při použití
require. Ve výchozím nastavení se přidaná knihovna přidá na konec seznamu knihoven k prohledání. PředánímTrueji předřadíte na začátek seznamu.Navíc lze přidanou knihovnu explicitně vyžádat pomocí
require("name", library="library").
- package(package_path, files=None, base_path='.', opt=None)¶
Zmrazí celý balíček — adresář souborů
.py(volitelně s podbalíčky) — aby jej bylo možné importovat jakoimport <package>. Pro jeden samostatný soubor použijte místo tohomodule.To je ekvivalentní zkopírování adresáře „package_path“ do zařízení (s výjimkou toho, že jde o zmrazený kód).
V nejjednodušším případě, pro zmrazení balíčku „foo“ v aktuálním adresáři:
package("foo")rekurzivně zahrne všechny soubory .py ve foo a zmrazí je jako
foo/**/*.py.Pokud balíček není ve stejném adresáři jako soubor manifestu, použijte
base_path:package("foo", base_path="path/to/libraries")Ve
base_pathmůžete použít výše uvedené proměnné, například$(PORT_DIR).Pro omezení na určité soubory v balíčku použijte
files(poznámka: cesty by měly být relativní k balíčku):package("foo", files=["bar/baz.py"]).
- module(module_path, base_path='.', opt=None)¶
Zmrazí jeden samostatný soubor
.py, aby jej bylo možné importovat podle jeho názvu (module("foo.py")umožní fungováníimport foo). Pro adresář/balíček použijtepackage.Pokud je soubor v aktuálním adresáři:
module("foo.py")Jinak použijte base_path k lokalizaci souboru:
module("foo.py", base_path="src/drivers")Ve
base_pathmůžete použít výše uvedené proměnné, například$(PORT_DIR).
- require(name, library=None)¶
Vyžádá balíček podle názvu (a jeho závislosti) z micropython-lib.
Takto se zmrazují rozšíření standardní knihovny a komunitní ovladače: pojmenovaný balíček se získá ze submodulu micropython-lib a zmrazí se spolu se vším, na čem závisí. Pro zmrazení vlastního zdrojového kódu místo publikovaného balíčku použijte
modulenebopackage.Volitelně lze zadat library (řetězec) pro odkaz na balíček z knihovny, která byla dříve zaregistrována pomocí
add_library. Jinak se použije seznam cest ke knihovnám.
- include(manifest_path)¶
Zahrne další manifest. Takto se manifesty skládají: vlastní manifest firmwaru by měl pomocí
includezahrnout manifest portu (nebo desky), aby moduly, které deska potřebuje, zůstaly zmrazené, a poté přidat své vlastní položky.Manifest používaný pro kompilaci firmwaru obvykle bude muset zahrnovat manifest portu, který může obsahovat zmrazené moduly potřebné pro fungování desky.
Argument manifest může být řetězec (název souboru) nebo iterovatelný objekt řetězců.
Relativní cesty se rozlišují vzhledem k aktuálnímu souboru manifestu.
Pokud cesta vede k adresáři, implicitně zahrnuje soubor manifest.py uvnitř tohoto adresáře.
Ve
manifest_pathmůžete použít výše uvedené proměnné, například$(PORT_DIR).
- metadata(description=None, version=None, license=None, author=None)¶
Definuje metadata pro tento soubor manifestu. To je užitečné pro manifesty balíčků micropython-lib.
Tato pole se zpracovávají, když je balíček publikován do / instalován z micropython-lib přes mip; v manifestu firmwaru desky nejsou potřeba.
Funkce nízké úrovně¶
Tyto funkce jsou zde zdokumentovány pro úplnost, ale s výjimkou freeze_as_str je veškerá funkcionalita přístupná přes funkce vysoké úrovně.
Funkce freeze* se liší pouze v tom, jak je kód uložen:
freeze_as_mpy/freeze_mpyukládají do flash předkompilovaný bytecode (.mpy). Kód běží přímo z flash, využívá minimum RAM a rychle se importuje. To je to, comodule,packagearequirepoužívají interně.freeze_as_strmísto toho zmrazí zdrojový kód Python, který se kompiluje do bytecode při importu (s využitím RAM a vyžadující kompilátor na zařízení). To je jediná schopnost, kterou funkce vysoké úrovně nevystavují, a proto je výše uvedenou výjimkou.
- freeze(path, script=None, opt=0)¶
Základní primitivum, na kterém funkce vysoké úrovně staví; upřednostněte je. Zmrazí vstup zadaný pomocí path a automaticky určí jeho typ. Skript
.pyse nejprve zkompiluje do.mpya poté zmrazí, soubor.mpyse zmrazí přímo.path musí být adresář, který je základním adresářem pro zahájení vyhledávání souborů. Při importu výsledných zmrazených modulů začne název modulu za path, tj. path je z názvu modulu vyloučena.
Pokud je path relativní, rozlišuje se vzhledem k aktuálnímu
manifest.py.Pokud je script None, zmrazí se všechny soubory v path.
Pokud je script iterovatelný objekt, pak se
freeze()zavolá na všechny položky iterovatelného objektu (se stejnými předanými hodnotami path a opt).Pokud je script řetězec, pak specifikuje soubor nebo adresář ke zmrazení a může před souborem nebo posledním adresářem obsahovat další adresáře. Soubor nebo adresář se bude hledat v path. Pokud je script adresář, pak se zmrazí všechny soubory v tomto adresáři.
opt je úroveň optimalizace předávaná do mpy-cross při kompilaci
.pydo.mpy. Tyto úrovně jsou popsány vmicropython.opt_level().
- freeze_as_str(path)¶
Zmrazí zadanou cestu path a všechny skripty
.pyv ní jako řetězec, který bude zkompilován při importu. Použijte toto pouze tehdy, když zmrazený kód musí zůstat zdrojovým kódem Python; oproti variantám.mpyto stojí RAM při importu.
- freeze_as_mpy(path, script=None, opt=0)¶
Zmrazí vstup tak, že nejprve zkompiluje skripty
.pydo souborů.mpya poté zmrazí výsledné soubory.mpy. To je to, comoduleapackagedělají pod kapotou. Další podrobnosti o argumentech vizfreeze().
- freeze_mpy(path, script=None, opt=0)¶
Zmrazí vstup, kterým musí být soubory
.mpyzmrazené přímo (bez kroku kompilace). Další podrobnosti o argumentech vizfreeze().
Příklady¶
Pro zmrazení jednoho souboru z aktuálního adresáře, který bude dostupný jako import mydriver, použijte:
module("mydriver.py")
Pro zmrazení adresáře souborů v podadresáři „mydriver“ aktuálního adresáře, který bude dostupný jako import mydriver, použijte:
package("mydriver")
Pro zmrazení knihovny „hmac“ z micropython-lib použijte:
require("hmac")
Úplnější příklad vlastního souboru manifest.py (pro desku, která má svůj vlastní výchozí manifest) je:
# Include the board's default manifest.
include("$(BOARD_DIR)/manifest.py")
# Add a custom driver
module("mydriver.py")
# Add aiorepl from micropython-lib
require("aiorepl")
Poté lze desku zkompilovat pomocí
$ cd ports/stm32
$ make BOARD=MYBOARD FROZEN_MANIFEST=~/src/myproject/manifest.py
Všimněte si, že většina desek nemá svůj vlastní manifest.py, místo toho používají přímo manifest portu; v takovém případě by váš manifest měl jednoduše použít include("$(PORT_DIR)/boards/manifest.py").