MicroPython for Microcontrollers Module 2
The language on a chip: MicroPython vs CPython interview questions
Interview questions on “The language on a chip: MicroPython vs CPython”: warm-ups, then what each harder question tests and how a good answer starts.
Warm-up questions
Short questions with short answers, each answered in full.
-
Fresher
MicroPython 1.29.0 reports sys.version_info as (3, 4, 0). Why, and what should code check instead?
Answered in the lesson Which Python is this? Feature levels and probes
-
Fresher
Does a plain dict keep insertion order on MicroPython 1.29.0?
Answered in the lesson Syntax and built-ins that differ from CPython
-
Fresher
Why does 16777217.0 come back as 16777216.0 on a Pico?
Answered in the lesson Numbers, bytes and text on small chips
-
Fresher
What does it mean that a MicroPython built-in module is extensible?
Answered in the lesson Imports, modules and packages on a device
-
Fresher
How do you write a traceback to a file on MicroPython, and why does traceback.print_exc() not work there?
Answered in the lesson Errors, tracebacks and logging without a screen
Questions with model answers
What each question tests, the first step of a good answer and the follow-ups to expect.
-
Fresher to mid
Your sensor library's tests run on CPython in CI and pass. On a Pico with MicroPython 1.29.0 the library fails at import with SyntaxError, pointing at a debug line, print(f'{reading = }'). Why does one debug line stop the whole module, and what do you change in the code and in CI?
- What it tests
- That a board compiles a whole module at import, the limits of MicroPython's f-string parser, and running tests on a MicroPython build as well as CPython.
- First step
- Reproduce it away from the board: compile the line at the Pico's prompt or on the unix port. MicroPython's lexer makes {name=} a self-documenting field only when the = comes straight before the closing brace, a format or a conversion, so with spaces the field is an expression it cannot compile, and the whole file fails before any of its lines runs.
- Follow-ups
-
- Why did no test catch it?
- Which step in CI would have stopped it?
- What else in f-strings differs from CPython?
From the lesson Which Python is this? Feature levels and probes
Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.Opening the model answers with your pass…
Model answers open with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so the model answers can’t be opened at the moment. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
Your app runs on Pico and ESP32 boards and, for a web demo, in MicroPython's browser build. A teammate wants t-strings in the report formatter, because the demo build has them. How would you allow that without breaking the boards, and would you?
- What it tests
- Feature levels per build, why a SyntaxError cannot be caught in its own file, choosing modules with a probe, and weighing the cost of two code paths.
- First step
- Check the levels before the design: t-strings need the FULL level, which the browser's pyscript variant has and the rp2 and esp32 builds do not. Any file that contains a t-string fails to import on the boards, so the only safe shape is two modules with one API, chosen at start by a compile() probe on a string.
- Follow-ups
-
- How do you test both code paths?
- What does the split cost on the boards?
- When is one plain module the better answer?
From the lesson Which Python is this? Feature levels and probes
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A Pico and an ESP32 board run the same code on MicroPython 1.29.0 and send their readings as JSON. A test that compares each payload with a stored string passes for the ESP32 board and fails for the Pico. Why, and how do you make the payloads identical?
- What it tests
- That a MicroPython dict gives keys in hash-table order, that the order depends on the port's hash size and the table's growth, and building ordered or canonical JSON without sort_keys.
- First step
- Print list(payload) on both boards before blaming the network. The orders differ because a plain dict iterates its hash table slot by slot, and the rp2 port keeps 8-bit string hashes while the esp32 port keeps 16-bit ones, so the same keys land in different slots. The stored string happened to match the ESP32 board's order.
- Follow-ups
-
- Why did the test pass while the payload had four keys?
- How would you produce sorted keys without sort_keys?
- Should the server compare JSON as text at all?
From the lesson Syntax and built-ins that differ from CPython
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
You must make a 300-line CPython utility module run on MicroPython 1.29.0 without forking it. It uses str.removeprefix, int.bit_length, json.dumps(indent=2), a regex with named groups and a dataclass. How do you plan and carry out the port, and how do you keep it from breaking again?
- What it tests
- Turning the differences pages into an inventory, choosing between portable code, small shims and probes, and a test setup that runs on CPython and on MicroPython for every change.
- First step
- Inventory before editing: compile and import the module on the unix port to find the syntax errors, then run its tests there to find the missing methods and options. Sort each finding into portable rewrite, shim or probe, and prefer the portable rewrite, because it leaves one code path for both Pythons.
- Follow-ups
-
- Where do shims belong, and how do they decide what to fill in?
- How do you replace the dataclass?
- What runs in CI to keep the port working?
From the lesson Syntax and built-ins that differ from CPython
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A Pico meters a 20 W load: every 100 ms it adds the energy of that interval, 2 joules, to a float total. After about three weeks the total stops growing, although the load still runs. Explain it with numbers, and redesign the counter.
- What it tests
- How single-precision rounding depends on the size of the total, working out when increments vanish, and an integer design that stays exact.
- First step
- Look at the size of the total, not the increment. A single-precision float keeps 24 bits, so once the total is large enough, half the gap between neighbouring values is more than 2 J, and each addition rounds back to the same total. Work out the total at which that happens, then how many additions it takes to get there.
- Follow-ups
-
- Would a 200 W load stall sooner?
- Why not switch the board to double precision?
- How do you report kilowatt-hours from an integer counter?
From the lesson Numbers, bytes and text on small chips
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
Design the binary frame that a battery-powered Pico sends to a CPython server: temperature, humidity, battery voltage and a reading counter. Which fields, types and order do you choose, and how do servers that are already deployed keep reading frames once you add a field?
- What it tests
- Choosing struct types from each field's range and resolution, explicit byte order, fixed-point units, a CRC, and versioning that lets old and new readers coexist.
- First step
- Start from each field's range and resolution, because they decide its type: -40.00 to 85.00 degrees in hundredths fits a signed 16-bit field, and so does a voltage in millivolts. Fix the byte order with > for every field, put a version and a length first, and end with a CRC over everything before it.
- Follow-ups
-
- Why not send JSON instead?
- How do you add a field without breaking old servers?
- Which checks does the server make before it trusts a frame?
From the lesson Numbers, bytes and text on small chips
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
After a deployment, one board fails at start with ImportError: can't import name Pin, while twenty others work. Its /lib holds a machine.py that nobody meant to copy. Explain what happened, how you prove it at the REPL in under a minute, and how you stop test files reaching boards again.
- What it tests
- MicroPython's import order and extensible built-ins, quick evidence at the REPL, and a deployment that copies only what belongs on the board.
- First step
- Name the rule first: machine is one of the extensible built-ins, so a file called machine.py on sys.path is found before the firmware's own module, and every import of machine on that board loads the file. Then show it at the REPL with two lookups that tell a file module from the built-in.
- Follow-ups
-
- What do you type at the REPL to prove it?
- Why did only one board fail?
- What would you change in how tests get their fakes?
From the lesson Imports, modules and packages on a device
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A board app has grown to 30 modules in /lib. Its tests must run on CPython and on the unix port in CI, and other teams will install its drivers with mip. How do you name and lay out the code so that every import resolves the same everywhere, and what keeps it that way?
- What it tests
- MicroPython's import order and extensible built-ins, package rules (one folder, relative imports), where mip installs, MICROPYPATH, and checks in CI that catch a name clash or a fake before a board does.
- First step
- Name things so the import order cannot surprise you: one top-level package with a name that no built-in, frozen module or micropython-lib package uses, holding every module as a submodule. Then the only top-level name the app adds to sys.path is the package, and the board, CI and mip all find it in a folder ending in /lib.
- Follow-ups
-
- How do the tests reach the hardware without a file called machine.py?
- What does a mip install of your drivers need from the repository?
- Which checks in CI catch a clash before a board does?
From the lesson Imports, modules and packages on a device
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A CPython library defines its own exceptions: a base class whose __init__ calls Exception.__init__ and sets a code attribute, errors re-raised with raise ... from, notes added with add_note(), and an ExceptionGroup for batch failures. What breaks on MicroPython 1.29.0, and how do you redesign the hierarchy to work on both?
- What it tests
- MicroPython's limits on exception subclasses, attributes and chaining, the missing ExceptionGroup and except*, and a design that keeps the information callers need without those features.
- First step
- Go through the features one by one against the differences pages: Exception.__init__ does not exist as a method to call, a cause given with from is dropped, add_note() is missing, and neither ExceptionGroup nor except* exists. A subclass may keep attributes of its own, so the redesign moves every piece of information into them.
- Follow-ups
-
- Where does the information that from carried go now?
- How do you report many failures from one batch?
- Which tests prove the redesign on both Pythons?
From the lesson Errors, tracebacks and logging without a screen
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A battery-powered Pico in a remote field must keep a record of every failure for months, on its 1,408 KiB filesystem, through power cuts and resets, and upload it when a phone comes near. Design the error log: what goes into each record, how big it may grow, and how it behaves when things go wrong.
- What it tests
- What makes a field failure diagnosable later, sizing a log against the flash, write and power-cut behaviour, repeated errors, and a log that can never stop the device.
- First step
- Decide what a record must answer later: which build, which boot, how long after the boot, what failed and how often. Then size it: a fixed share of the 1,408 KiB, for example 64 KiB, divided by the record size gives how many records survive, which decides how much detail each record can afford.
- Follow-ups
-
- How do you timestamp records without a real-time clock?
- What do you do about an error that repeats every second?
- How do you upload the log without losing records written meanwhile?
From the lesson Errors, tracebacks and logging without a screen
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
All MicroPython for Microcontrollers interview questions · The MicroPython for Microcontrollers track