mirror of
https://github.com/micropython/micropython.git
synced 2026-01-10 14:07:14 +01:00
py/objexcept: Support errno attribute on OSError exceptions.
This commit adds the errno attribute to exceptions, so code can retrieve errno codes from an OSError using exc.errno. The implementation here simply lets `errno` (and the existing `value`) attributes work on any exception instance (they both alias args[0]). This is for efficiency and to keep code size down. The pros and cons of this are: Pros: - more compatible with CPython, less difference to document and learn - OSError().errno will correctly return None, whereas the current way of doing it via OSError().args[0] will raise an IndexError - it reduces code size on most bare-metal ports (because they already have the errno qstr) - for Python code that uses exc.errno the generated bytecode is 2 bytes smaller and more efficient to execute (compared with exc.args[0]); so bytecode loaded to RAM saves 2 bytes RAM for each use of this attribute, and bytecode that is frozen saves 2 bytes flash/ROM for each use - it's easier/shorter to type, and saves 2 bytes of space in .py files that use it (for each use) Cons: - increases code size by 4-8 bytes on minimal ports that don't already have the `errno` qstr - all exceptions now have .errno and .value attributes (a cpydiff test is added to address this) See also #2407. Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
# test basic properties of exceptions
|
||||
|
||||
print(repr(IndexError()))
|
||||
print(str(IndexError()))
|
||||
|
||||
@@ -12,3 +14,6 @@ s = StopIteration()
|
||||
print(s.value)
|
||||
s = StopIteration(1, 2, 3)
|
||||
print(s.value)
|
||||
|
||||
print(OSError().errno)
|
||||
print(OSError(1, "msg").errno)
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# test subclassing a native exception
|
||||
|
||||
|
||||
class MyExc(Exception):
|
||||
pass
|
||||
|
||||
|
||||
e = MyExc(100, "Some error")
|
||||
print(e)
|
||||
print(repr(e))
|
||||
@@ -20,3 +24,19 @@ try:
|
||||
raise MyExc("Some error2")
|
||||
except:
|
||||
print("Caught user exception")
|
||||
|
||||
|
||||
class MyStopIteration(StopIteration):
|
||||
pass
|
||||
|
||||
|
||||
print(MyStopIteration().value)
|
||||
print(MyStopIteration(1).value)
|
||||
|
||||
|
||||
class MyOSError(OSError):
|
||||
pass
|
||||
|
||||
|
||||
print(MyOSError().errno)
|
||||
print(MyOSError(1, "msg").errno)
|
||||
|
||||
9
tests/cpydiff/types_exception_attrs.py
Normal file
9
tests/cpydiff/types_exception_attrs.py
Normal file
@@ -0,0 +1,9 @@
|
||||
"""
|
||||
categories: Types,Exception
|
||||
description: 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.
|
||||
"""
|
||||
e = Exception(1)
|
||||
print(e.value)
|
||||
print(e.errno)
|
||||
Reference in New Issue
Block a user