Open-source project
micropython/micropython avatar
micropython/micropython

MicroPython: Python 3 on Microcontrollers, From Build to First Script

MicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems

22,108 stars8,983 forksCNOASSERTION

At a glance

What is it?
MicroPython runs a subset of Python 3.4 syntax, plus async/await and selected later features, on microcontrollers and constrained systems. This review covers what it is for, how the ports are built, what a first session looks like, and where CPython or C remains the better choice.
Who is it for?
Adopt MicroPython when the target is a supported microcontroller port and the work is I/O, sensor loops, or glue between peripherals where Python-level iteration speed is acceptable. Skip it when you need the full CPython standard library, native thread performance, or a platform that has no port in the ports/ directory; a C toolchain or CPython on a Linux SBC is the better fit there.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What MicroPython is for, and who ends up using it

MicroPython is an implementation of Python 3.x for microcontrollers, embedded systems and other constrained platforms. The README states that it implements the entire Python 3.4 syntax, including exceptions, with, and yield from, plus the async and await keywords from Python 3.5 and some select features from later versions. That is the promise: a real language, not a macro dialect, on a device with kilobytes of RAM.

The intended user is someone who wants fine control over attached hardware without writing the whole application in C. The README describes the design goal as a bare-metal feeling, with very little between the programmer and the physical world. In practice that means GPIO, Timers, ADC, DAC, PWM, SPI, I2C, CAN, Bluetooth and USB are reachable through MicroPython-specific modules rather than through a vendor SDK.

It is not a desktop Python. The core datatypes are there (str with basic Unicode support, bytes, bytearray, tuple, list, dict, set, frozenset, array.array, collections.namedtuple, classes and instances) and the builtin modules include os, sys, time, re and struct. But the README is explicit that only a subset of Python 3 functionality is implemented for the data types and modules. Ports vary: some have _thread, socket, ssl and asyncio, others do not.

How the repository is split, and where your code actually runs

The repository layout tells you most of what you need to know about the architecture. py/ holds the core implementation: compiler, runtime and core library. ports/ holds platform-specific code for each architecture. extmod/ holds additional non-core modules implemented in C. mpy-cross/ is the cross-compiler that turns scripts into precompiled bytecode. lib/ contains submodules for external dependencies, shared/ holds code used by more than one port, and tools/ contains utilities including the pyboard.py module.

Scripts execute in one of two forms. The README says MicroPython can execute textual source (.py files) or precompiled bytecode (.mpy files), in both cases either from an on-device filesystem or frozen into the MicroPython executable. That distinction matters operationally. A .py file on the device filesystem can be edited in place over the REPL or a file-transfer tool. A frozen module is compiled into the firmware image, which costs a rebuild and a reflash every time the code changes but removes the file from RAM and the filesystem.

mpy-cross is the piece that makes the second path practical. It compiles on a host machine, so the target never pays for parsing and compiling Python source. If you are shipping a fixed application to many boards, that is the workflow the repository is built around.

Building and running MicroPython on the Unix port

The README says make is used to build the components, or gmake on BSD-based systems, and that you need bash, gcc, and Python 3.3+ available as the command python3. Some ports, specifically rp2 and esp32, additionally use CMake. The quickest way to see the runtime without a board is the Unix port.

From the repository root, change into the Unix port directory and build. The resulting binary is the interpreter for your host.

bash
cd ports/unix
make

After the build finishes you get an executable in that directory. Running it drops you into the MicroPython REPL on your own machine, which is the same interactive environment the documentation describes for hardware. You can import modules, test expressions and confirm language behaviour before touching a microcontroller.

bash
./micropython

For a real device, the entry point is the board's port directory. The pyboard is the officially supported board from the original Kickstarter campaign, and the README points to its schematics, pinouts and quick reference. Flashing a board is port-specific and the README does not document the flashing procedure itself; it directs readers to the online documentation for API reference and usage. Treat the port directory and docs as the authority for your specific chip.

The gap between MicroPython and CPython is real

The most common misunderstanding is that a script written for CPython will run unchanged. The README claims that at first glance MicroPython should look just like regular Python and that most Python scripts should run unchanged, even on devices with very tight resources. That claim holds for small scripts and falls apart quickly for anything that depends on the standard library beyond the subset provided.

There is no CPython C extension support. The built-in modules are described in the README as an efficient subset of the corresponding Python ones, without duplication of functionality, and they allow extension in Python if needed. So a dependency that pulls in a compiled wheel is out. A dependency that is pure Python may work, if it stays inside the implemented subset and fits in RAM.

Execution speed is the second gap. MicroPython is an interpreter running on a microcontroller; the README makes no performance claims and the repository contains no benchmark comparison against C. If a control loop needs microsecond-level determinism, the interpreter's bytecode dispatch is in the way, and the native module path (examples/natmod/ exists in the repository) or plain C is the answer. Choosing MicroPython for a hard real-time loop is a mistake that shows up late, after the application is written.

Where another tool fits better: CircuitPython and CPython

CircuitPython is the closest alternative and the difference is in approach, not just branding. CircuitPython is a fork aimed at education and beginner boards: it presents a USB mass-storage drive where you drop code.py, and the board reboots and runs it. MicroPython does not standardise that workflow. It gives you a REPL, a device filesystem you manage yourself, and a build system that expects you to produce firmware for a named port. If your priority is a board that behaves like a USB stick, CircuitPython removes a step that MicroPython leaves to you.

The other alternative is not a fork at all: run CPython on a Linux single-board computer. You get the full standard library, native C extensions and pip. You also get an operating system, a boot sequence measured in seconds, and power draw that a battery-powered sensor node cannot afford. MicroPython's reason to exist is the case where that trade is unacceptable.

A third path is the vendor C SDK. It gives the tightest control and the best performance, at the cost of writing peripheral setup by hand and rebuilding for every change. MicroPython sits between these: faster to iterate than C, far lighter than Linux.

Releases, ports and what an upgrade actually costs

The release notes show the shape of the project's cadence. v1.29.0 added a psoc-edge port, CAN on alif and mimxrt, mem_backup and manifest c_module. v1.28.0 added PWM on alif and stm32, a new machine.CAN API, t-strings and the weakref module. v1.27.0 added ESP32C5, ESP32P4 and STM32U5 support, an enhanced test suite and port Tier levels. The last push to the default branch was on 2026-09-19, so the repository is active rather than archived.

The upgrade cost is concentrated in two places. First, the machine API: the v1.28.0 notes describe a new machine.CAN API, and an API change of that kind means code written against the previous interface needs editing, not just a reflash. Second, the port tier system introduced in v1.27.0 is a signal about how much attention a given platform receives. A port can exist and still lag on features; the tier is the project's own way of saying so.

On licensing, the README states that MicroPython is licenced under the MIT license and that all contributions should follow this license. The repository metadata reports the license as NOASSERTION, which is a GitHub classification artifact, not a different grant. MIT is permissive: you can ship it in a commercial product. That is not legal advice, and if you are combining MicroPython with vendor SDK code or a proprietary library, check the terms of those separately.

What to check before you commit a product to it

Start with the port, not the language. Confirm that a directory exists under ports/ for your exact chip and that the features you need are implemented there. CAN, Bluetooth and networking are not uniform across ports; the README says some ports have _thread, socket, ssl and asyncio, which implies others do not. A feature list for one board tells you nothing about another.

Then decide how code reaches the device. If the application is fixed, freezing modules into the firmware and using mpy-cross gives the smallest runtime footprint. If it changes often, keep .py files on the device filesystem and accept the RAM and parse cost. The README supports both, and the choice affects your build pipeline more than your source code.

Finally, size the RAM budget early. The README's design values lead with minimalism and efficiency, and the built-in modules are deliberately a subset rather than the full library. A prototype that fits in the REPL is not evidence that the finished application fits. Load the real data structures and the real module set on the real board before you write the second half of the firmware.

Editorial conclusion

Adopt MicroPython when the target is a supported microcontroller port and the work is I/O, sensor loops, or glue between peripherals where Python-level iteration speed is acceptable. Skip it when you need the full CPython standard library, native thread performance, or a platform that has no port in the ports/ directory; a C toolchain or CPython on a Linux SBC is the better fit there. Before committing, verify the tier and board support for your exact chip in the docs, confirm the CAN or Bluetooth module exists on that port rather than assuming it does, and check whether your firmware needs a frozen manifest or can ship as a plain .py file on the device filesystem.

Frequently asked questions

Is MicroPython the same as Python?

No. MicroPython implements the entire Python 3.4 syntax plus async/await from 3.5 and some later features, but the README states that only a subset of Python 3 functionality is implemented for the data types and modules. The built-in modules are described as an efficient subset of the corresponding Python ones.

Is MicroPython still being used today?

The repository is not archived and the last push to the default branch was on 2026-09-19. Recent releases include v1.29.0, v1.28.0 and v1.27.0, which added new ports, CAN support on alif and mimxrt, and ESP32C5, ESP32P4 and STM32U5 support.

How do I install MicroPython?

The README says make is used to build the components, or gmake on BSD-based systems, and that you need bash, gcc and Python 3.3+ available as python3. Some ports, rp2 and esp32, additionally use CMake. For API reference and usage information it points to the online documentation at docs.micropython.org.

How do I use MicroPython on an ESP32?

The esp32 port is one of the ports that additionally uses CMake for its build, alongside rp2. Release v1.27.0 added ESP32C5 and ESP32P4 support, so the specific ESP32 variant determines what is available. The README does not document the flashing procedure; it directs readers to the online documentation.

What is MicroPython used for?

It is used to run Python on microcontrollers and constrained systems, giving access to hardware peripherals. The README lists MicroPython-specific modules for GPIO, Timers, ADC, DAC, PWM, SPI, I2C, CAN, Bluetooth and USB, and describes the goal as a bare-metal feeling with little between the programmer and the physical world.

Official sources

  1. Issues
  2. micropython/micropython on GitHub
  3. Project website
  4. README
  5. Releases
For maintainers

Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/micropython-micropython.svg)](https://hysenlabs.com/projects/micropython-micropython)
Community notes

Community notes