Builtin types¶
Generated Sat 26 Oct 2024 12:10:17 UTC
Exception¶
All exceptions have readable value
and errno
attributes, not just StopIteration
and OSError
.¶
Cause: MicroPython is optimised to reduce code size.
Workaround: Only use value
on StopIteration
exceptions, and errno
on OSError
exceptions. Do not use or rely on these attributes on other exceptions.
Sample code:
e = Exception(1)
print(e.value)
print(e.errno)
CPy output: |
uPy output: |
Traceback (most recent call last):
File "<stdin>", line 8, in <module>
AttributeError: 'Exception' object has no attribute 'value'
|
1
1
|
Exception chaining not implemented¶
Sample code:
try:
raise TypeError
except TypeError:
raise ValueError
CPy output: |
uPy output: |
Traceback (most recent call last):
File "<stdin>", line 8, in <module>
TypeError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 10, in <module>
ValueError
|
Traceback (most recent call last):
File "<stdin>", line 10, in <module>
ValueError:
|
User-defined attributes for builtin exceptions are not supported¶
Cause: MicroPython is highly optimized for memory usage.
Workaround: Use user-defined exception subclasses.
Sample code:
e = Exception()
e.x = 0
print(e.x)
CPy output: |
uPy output: |
0
|
Traceback (most recent call last):
File "<stdin>", line 8, in <module>
AttributeError: 'Exception' object has no attribute 'x'
|
Exception in while loop condition may have unexpected line number¶
Cause: Condition checks are optimized to happen at the end of loop body, and that line number is reported.
Sample code:
l = ["-foo", "-bar"]
i = 0
while l[i][0] == "-":
print("iter")
i += 1
CPy output: |
uPy output: |
iter
iter
Traceback (most recent call last):
File "<stdin>", line 10, in <module>
IndexError: list index out of range
|
iter
iter
Traceback (most recent call last):
File "<stdin>", line 12, in <module>
IndexError: list index out of range
|
Exception.__init__ method does not exist.¶
Cause: Subclassing native classes is not fully supported in MicroPython.
Workaround: Call using super()
instead:
class A(Exception):
def __init__(self):
super().__init__()
Sample code:
class A(Exception):
def __init__(self):
Exception.__init__(self)
a = A()
CPy output: |
uPy output: |
Traceback (most recent call last):
File "<stdin>", line 18, in <module>
File "<stdin>", line 15, in __init__
AttributeError: type object 'Exception' has no attribute '__init__'
|
bytearray¶
Array slice assignment with unsupported RHS¶
Sample code:
b = bytearray(4)
b[0:1] = [1, 2]
print(b)
CPy output: |
uPy output: |
bytearray(b'\x01\x02\x00\x00\x00')
|
Traceback (most recent call last):
File "<stdin>", line 8, in <module>
NotImplementedError: array/bytes required on right side
|
bytes¶
bytes objects support .format() method¶
Cause: MicroPython strives to be a more regular implementation, so if both str
and bytes
support __mod__()
(the % operator), it makes sense to support format()
for both too. Support for __mod__
can also be compiled out, which leaves only format()
for bytes formatting.
Workaround: If you are interested in CPython compatibility, don’t use .format()
on bytes objects.
Sample code:
print(b"{}".format(1))
CPy output: |
uPy output: |
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
AttributeError: 'bytes' object has no attribute 'format'
|
b'1'
|
bytes() with keywords not implemented¶
Workaround: Pass the encoding as a positional parameter, e.g. print(bytes('abc', 'utf-8'))
Sample code:
print(bytes("abc", encoding="utf8"))
CPy output: |
uPy output: |
b'abc'
|
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
NotImplementedError: keyword argument(s) not implemented - use normal args instead
|
Bytes subscription with step != 1 not implemented¶
Cause: MicroPython is highly optimized for memory usage.
Workaround: Use explicit loop for this very rare operation.
Sample code:
print(b"123"[0:3:2])
CPy output: |
uPy output: |
b'13'
|
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
NotImplementedError: only slices with step=1 (aka None) are supported
|
dict¶
Dictionary keys view does not behave as a set.¶
Cause: Not implemented.
Workaround: Explicitly convert keys to a set before using set operations.
Sample code:
print({1: 2, 3: 4}.keys() & {1})
CPy output: |
uPy output: |
{1}
|
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
TypeError: unsupported types for __and__: 'dict_view', 'set'
|
float¶
uPy allows implicit conversion of objects in maths operations while CPython does not.¶
Workaround: Objects should be wrapped in float(obj)
for compatibility with CPython.
Sample code:
class Test:
def __float__(self):
return 0.5
print(2.0 * Test())
CPy output: |
uPy output: |
Traceback (most recent call last):
File "<stdin>", line 14, in <module>
TypeError: unsupported operand type(s) for *: 'float' and 'Test'
|
1.0
|
uPy and CPython outputs formats may differ¶
Sample code:
print("%.1g" % -9.9)
CPy output: |
uPy output: |
-1e+01
|
-10
|
int¶
bit_length
method doesn’t exist.¶
Cause: bit_length method is not implemented.
Workaround: Avoid using this method on MicroPython.
Sample code:
x = 255
print("{} is {} bits long.".format(x, x.bit_length()))
CPy output: |
uPy output: |
255 is 8 bits long.
|
Traceback (most recent call last):
File "<stdin>", line 9, in <module>
AttributeError: 'int' object has no attribute 'bit_length'
|
No int conversion for int-derived types available¶
Workaround: Avoid subclassing builtin types unless really needed. Prefer https://en.wikipedia.org/wiki/Composition_over_inheritance .
Sample code:
class A(int):
__add__ = lambda self, other: A(int(self) + other)
a = A(42)
print(a + a)
CPy output: |
uPy output: |
84
|
Traceback (most recent call last):
File "<stdin>", line 14, in <module>
File "<stdin>", line 10, in <lambda>
TypeError: unsupported types for __radd__: 'int', 'int'
|
to_bytes
method doesn’t implement signed parameter.¶
Cause: The signed
keyword-only parameter is not implemented for int.to_bytes()
.
When the integer is negative, MicroPython behaves the same as CPython int.to_bytes(..., signed=True)
When the integer is non-negative, MicroPython behaves the same as CPython int.to_bytes(..., signed=False)
.
(The difference is subtle, but in CPython a positive integer converted with signed=True
may require one byte more in the output length, in order to fit the 0 sign bit.)
Workaround: Take care when calling to_bytes()
on an integer value which may be negative.
Sample code:
x = -1
print(x.to_bytes(1, "big"))
CPy output: |
uPy output: |
Traceback (most recent call last):
File "<stdin>", line 16, in <module>
OverflowError: can't convert negative int to unsigned
|
b'\xff'
|
list¶
List delete with step != 1 not implemented¶
Workaround: Use explicit loop for this rare operation.
Sample code:
l = [1, 2, 3, 4]
del l[0:4:2]
print(l)
CPy output: |
uPy output: |
[2, 4]
|
Traceback (most recent call last):
File "<stdin>", line 8, in <module>
NotImplementedError:
|
List slice-store with non-iterable on RHS is not implemented¶
Cause: RHS is restricted to be a tuple or list
Workaround: Use list(<iter>)
on RHS to convert the iterable to a list
Sample code:
l = [10, 20]
l[0:1] = range(4)
print(l)
CPy output: |
uPy output: |
[0, 1, 2, 3, 20]
|
Traceback (most recent call last):
File "<stdin>", line 8, in <module>
TypeError: object 'range' isn't a tuple or list
|
List store with step != 1 not implemented¶
Workaround: Use explicit loop for this rare operation.
Sample code:
l = [1, 2, 3, 4]
l[0:4:2] = [5, 6]
print(l)
CPy output: |
uPy output: |
[5, 2, 6, 4]
|
Traceback (most recent call last):
File "<stdin>", line 8, in <module>
NotImplementedError:
|
memoryview¶
memoryview can become invalid if its target is resized¶
Cause: CPython prevents a bytearray
or io.bytesIO
object from changing size while there is a memoryview
object that references it. MicroPython requires the programmer to manually ensure that an object is not resized while any memoryview
references it.
In the worst case scenario, resizing an object which is the target of a memoryview can cause the memoryview(s) to reference invalid freed memory (a use-after-free bug) and corrupt the MicroPython runtime.
Workaround: Do not change the size of any bytearray
or io.bytesIO
object that has a memoryview
assigned to it.
Sample code:
b = bytearray(b"abcdefg")
m = memoryview(b)
b.extend(b"hijklmnop")
print(b, bytes(m))
CPy output: |
uPy output: |
Traceback (most recent call last):
File "<stdin>", line 11, in <module>
BufferError: Existing exports of data: object cannot be re-sized
|
bytearray(b'abcdefghijklmnop') b'abcdefg'
|
str¶
Start/end indices such as str.endswith(s, start) not implemented¶
Sample code:
print("abc".endswith("c", 1))
CPy output: |
uPy output: |
True
|
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
NotImplementedError: start/end indices
|
Attributes/subscr not implemented¶
Sample code:
print("{a[0]}".format(a=[1, 2]))
CPy output: |
uPy output: |
1
|
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
NotImplementedError: attributes not supported
|
str(…) with keywords not implemented¶
Workaround: Input the encoding format directly. eg print(bytes('abc', 'utf-8'))
Sample code:
print(str(b"abc", encoding="utf8"))
CPy output: |
uPy output: |
abc
|
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
NotImplementedError: keyword argument(s) not implemented - use normal args instead
|
str.ljust() and str.rjust() not implemented¶
Cause: MicroPython is highly optimized for memory usage. Easy workarounds available.
Workaround: Instead of s.ljust(10)
use "%-10s" % s
, instead of s.rjust(10)
use "% 10s" % s
. Alternatively, "{:<10}".format(s)
or "{:>10}".format(s)
.
Sample code:
print("abc".ljust(10))
CPy output: |
uPy output: |
abc
|
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
AttributeError: 'str' object has no attribute 'ljust'
|
None as first argument for rsplit such as str.rsplit(None, n) not implemented¶
Sample code:
print("a a a".rsplit(None, 1))
CPy output: |
uPy output: |
['a a', 'a']
|
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
NotImplementedError: rsplit(None,n)
|
Subscript with step != 1 is not yet implemented¶
Sample code:
print("abcdefghi"[0:9:2])
CPy output: |
uPy output: |
acegi
|
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
NotImplementedError: only slices with step=1 (aka None) are supported
|
tuple¶
Tuple load with step != 1 not implemented¶
Sample code:
print((1, 2, 3, 4)[0:4:2])
CPy output: |
uPy output: |
(1, 3)
|
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
NotImplementedError: only slices with step=1 (aka None) are supported
|