@@ -67,14 +67,18 @@ handler located at label `L1`.
67
67
Handling Exceptions
68
68
-------------------
69
69
70
- At runtime, when an exception occurs, the interpreter looks up
71
- the offset of the current instruction in the exception table. If
72
- it finds a handler, control flow transfers to it. Otherwise, the
70
+ At runtime, when an exception occurs, the interpreter calls
71
+ `` get_exception_handler() `` in
72
+ [ Python/ceval.c] ( https://github.com/python/cpython/blob/main/Python/ceval.c )
73
+ to look up the offset of the current instruction in the exception
74
+ table. If it finds a handler, control flow transfers to it. Otherwise, the
73
75
exception bubbles up to the caller, and the caller's frame is
74
76
checked for a handler covering the ` CALL ` instruction. This
75
77
repeats until a handler is found or the topmost frame is reached.
76
78
If no handler is found, the program terminates. During unwinding,
77
- the traceback is constructed as each frame is added to it.
79
+ the traceback is constructed as each frame is added to it by
80
+ `` PyTraceBack_Here() `` , which is in
81
+ [ Python/traceback.c] ( https://github.com/python/cpython/blob/main/Python/traceback.c ) .
78
82
79
83
Along with the location of an exception handler, each entry of the
80
84
exception table also contains the stack depth of the ` try ` instruction
@@ -169,33 +173,12 @@ which is then encoded as:
169
173
170
174
for a total of five bytes.
171
175
176
+ The code to construct the exception table is in `` assemble_exception_table() ``
177
+ in [ Python/assemble.c] ( https://github.com/python/cpython/blob/main/Python/assemble.c ) .
172
178
173
- Script to parse the exception table
174
- -----------------------------------
175
-
176
- ```
177
- def parse_varint(iterator):
178
- b = next(iterator)
179
- val = b & 63
180
- while b&64:
181
- val <<= 6
182
- b = next(iterator)
183
- val |= b&63
184
- return val
185
- ```
186
- ```
187
- def parse_exception_table(code):
188
- iterator = iter(code.co_exceptiontable)
189
- try:
190
- while True:
191
- start = parse_varint(iterator)*2
192
- length = parse_varint(iterator)*2
193
- end = start + length - 2 # Present as inclusive, not exclusive
194
- target = parse_varint(iterator)*2
195
- dl = parse_varint(iterator)
196
- depth = dl >> 1
197
- lasti = bool(dl&1)
198
- yield start, end, target, depth, lasti
199
- except StopIteration:
200
- return
201
- ```
179
+ The interpreter's function to lookup the table by instruction offset is
180
+ `` get_exception_handler() `` in
181
+ [ Python/ceval.c] ( https://github.com/python/cpython/blob/main/Python/ceval.c ) .
182
+ The Python function `` _parse_exception_table() `` in
183
+ [ Lib/dis.py] ( https://github.com/python/cpython/blob/main/Lib/dis.py )
184
+ returns the exception table content as a list of namedtuple instances.
0 commit comments