2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								Description of exception handling
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								---------------------------------
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Python uses a technique known as "zero-cost" exception handling, which
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								minimizes the cost of supporting exceptions. In the common case (where
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								no exception is raised) the cost is reduced to zero (or close to zero).
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								The cost of raising an exception is increased, but not by much.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								The following code:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								try:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    g(0)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								except:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    res = "fail"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								compiles into intermediate code like the following:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                  RESUME                   0
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     1            SETUP_FINALLY            8 (to L1)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     2            LOAD_NAME                0 (g)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                  PUSH_NULL
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                  LOAD_CONST               0 (0)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                  CALL                     1
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                  POP_TOP
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                  POP_BLOCK
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    --   L1:      PUSH_EXC_INFO
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     3            POP_TOP
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     4            LOAD_CONST               1 ('fail')
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                  STORE_NAME               1 (res)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								`SETUP_FINALLY`  and `POP_BLOCK`  are pseudo-instructions. This means
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								that they can appear in intermediate code but they are not bytecode
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								instructions. `SETUP_FINALLY`  specifies that henceforth, exceptions
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								are handled by the code at label L1. The `POP_BLOCK`  instruction
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								reverses the effect of the last `SETUP`  instruction, so that the
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								active exception handler reverts to what it was before.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								`SETUP_FINALLY`  and `POP_BLOCK`  have no effect when no exceptions
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								are raised. The idea of zero-cost exception handling is to replace
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								these pseudo-instructions by metadata which is stored alongside the
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								bytecode, and which is inspected only when an exception occurs.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								This metadata is the exception table, and it is stored in the code
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								object's `co_exceptiontable`  field.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								When the pseudo-instructions are translated into bytecode,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								`SETUP_FINALLY`  and `POP_BLOCK`  are removed, and the exception
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								table is constructed, mapping each instruction to the exception
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								handler that covers it, if any. Instructions which are not
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								covered by any exception handler within the same code object's
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								bytecode, do not appear in the exception table at all.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								For the code object in our example above, the table has a single
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								entry specifying that all instructions that were between the
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								`SETUP_FINALLY`  and the `POP_BLOCK`  are covered by the exception
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								handler located at label `L1` .
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Handling Exceptions
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								-------------------
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 16:28:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								At runtime, when an exception occurs, the interpreter calls
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 23:37:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								`get_exception_handler()`  in [Python/ceval.c ](../Python/ceval.c )
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 16:28:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								to look up the offset of the current instruction in the exception
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								table. If it finds a handler, control flow transfers to it. Otherwise, the
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								exception bubbles up to the caller, and the caller's frame is
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								checked for a handler covering the `CALL`  instruction. This
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								repeats until a handler is found or the topmost frame is reached.
							 
						 
					
						
							
								
									
										
										
										
											2024-10-05 00:48:12 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								If no handler is found, then the interpreter function
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 23:37:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								(`_PyEval_EvalFrameDefault()` ) returns NULL. During unwinding,
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 16:28:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								the traceback is constructed as each frame is added to it by
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 23:37:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								`PyTraceBack_Here()` , which is in [Python/traceback.c ](../Python/traceback.c ).
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Along with the location of an exception handler, each entry of the
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exception table also contains the stack depth of the `try`  instruction
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								and a boolean `lasti`  value, which indicates whether the instruction
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								offset of the raising instruction should be pushed to the stack.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Handling an exception, once an exception table entry is found, consists
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								of the following steps:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-01 18:12:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								1.  pop values from the stack until it matches the stack depth for the handler.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								2.  if `lasti`  is true, then push the offset that the exception was raised at.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								3.  push the exception to the stack.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								4.  jump to the target offset and resume execution.
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Reraising Exceptions and `lasti` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								--------------------------------
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								The purpose of pushing `lasti`  to the stack is for cases where an exception
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								needs to be re-raised, and be associated with the original instruction that
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								raised it. This happens, for example, at the end of a `finally`  block, when
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								any in-flight exception needs to be propagated on. As the frame's instruction
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								pointer now points into the finally block, a `RERAISE`  instruction
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								(with `oparg > 0` ) sets it to the `lasti`  value from the stack.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Format of the exception table
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								-----------------------------
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Conceptually, the exception table consists of a sequence of 5-tuples:
							 
						 
					
						
							
								
									
										
										
										
											2024-12-01 18:12:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								1.  `start-offset`  (inclusive)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								2.  `end-offset`  (exclusive)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								3.  `target` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								4.  `stack-depth` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								5.  `push-lasti`  (boolean)
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								All offsets and lengths are in code units, not bytes.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								We want the format to be compact, but quickly searchable.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								For it to be compact, it needs to have variable sized entries so that we can store common (small) offsets compactly, but handle large offsets if needed.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								For it to be searchable quickly, we need to support binary search giving us log(n) performance in all cases.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Binary search typically assumes fixed size entries, but that is not necessary, as long as we can identify the start of an entry.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								It is worth noting that the size (end-start) is always smaller than the end, so we encode the entries as:
							 
						 
					
						
							
								
									
										
										
										
											2024-12-01 18:12:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								`start, size, target, depth, push-lasti` .
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Also, sizes are limited to 2**30 as the code length cannot exceed 2**31 and each code unit takes 2 bytes.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								It also happens that depth is generally quite small.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								So, we need to encode:
							 
						 
					
						
							
								
									
										
										
										
											2024-12-01 18:12:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								```
							 
						 
					
						
							
								
									
										
										
										
											2024-12-01 18:12:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								start   (up to 30 bits)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								size    (up to 30 bits)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								target  (up to 30 bits)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								depth   (up to ~8 bits)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								lasti   (1 bit)
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								We need a marker for the start of the entry, so the first byte of entry will have the most significant bit set.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Since the most significant bit is reserved for marking the start of an entry, we have 7 bits per byte to encode offsets.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Encoding uses a standard varint encoding, but with only 7 bits instead of the usual 8.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								The 8 bits of a byte are (msb left) SXdddddd where S is the start bit. X is the extend bit meaning that the next byte is required to extend the offset.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								In addition, we combine `depth`  and `lasti`  into a single value, `((depth<<1)+lasti)` , before encoding.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								For example, the exception entry:
							 
						 
					
						
							
								
									
										
										
										
											2024-12-01 18:12:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								```
							 
						 
					
						
							
								
									
										
										
										
											2024-12-01 18:12:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								start:              20
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								end:                28
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								target:             100
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								depth:              3
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								lasti:              False
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								is encoded by first converting to the more compact four value form:
							 
						 
					
						
							
								
									
										
										
										
											2024-12-01 18:12:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								```
							 
						 
					
						
							
								
									
										
										
										
											2024-12-01 18:12:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								start:              20
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								size:               8
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								target:             100
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								depth< < 1 + lasti:      6 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								which is then encoded as:
							 
						 
					
						
							
								
									
										
										
										
											2024-12-01 18:12:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								```
							 
						 
					
						
							
								
									
										
										
										
											2024-12-01 18:12:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								148     (MSB + 20 for start)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								8       (size)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								65      (Extend bit + 1)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								36      (Remainder of target, 100 == (1< < 6 ) + 36 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								6
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								for a total of five bytes.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 23:37:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								The code to construct the exception table is in `assemble_exception_table()` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								in [Python/assemble.c ](../Python/assemble.c ).
							 
						 
					
						
							
								
									
										
										
										
											2024-06-03 10:36:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 16:28:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								The interpreter's function to lookup the table by instruction offset is
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 23:37:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								`get_exception_handler()`  in [Python/ceval.c ](../Python/ceval.c ).
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								The Python function `_parse_exception_table()`  in [Lib/dis.py ](../Lib/dis.py )
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 16:28:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								returns the exception table content as a list of namedtuple instances.
							 
						 
					
						
							
								
									
										
										
										
											2024-10-05 00:48:12 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Exception Chaining Implementation
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								---------------------------------
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								[Exception chaining ](https://docs.python.org/dev/tutorial/errors.html#exception-chaining )
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 23:37:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								refers to setting the `__context__`  and `__cause__`  fields of an exception as it is
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								being raised. The `__context__`  field is set by `_PyErr_SetObject()`  in
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								[Python/errors.c ](../Python/errors.c ) (which is ultimately called by all
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								`PyErr_Set*()`  functions).  The `__cause__`  field (explicit chaining) is set by
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								the `RAISE_VARARGS`  bytecode.