A code object records which source line each instruction came from in its
co_lnotab table. CPython’s compiler comment says that since version 2.3,
SET_LINENO instructions are never generated and offsets are mapped to source
lines through this table instead.
The co_lnotab table
co_lnotab is a string of byte pairs. The first byte of a pair is how far
the address moves on, in bytes of co_code. The second is how far the line
number moves on. Both are unsigned, so an address or a line can only go up.
To find the line of an instruction, start with address 0 and line
co_firstlineno. For each pair, add the first byte to the address. If the
address has now gone past the instruction, stop: the line so far is its line.
Otherwise add the second byte to the line and go on.
A step too big for one byte is spread over several pairs. A pair of 255 and 0 moves
the address 255 bytes without moving the line, and is repeated until the rest of the
address step fits. A pair of the remaining address step and 255 moves the line up by
255; once the line step fits, one last pair finishes it. So a step of 300 bytes and 3
lines is written as FF 00 2D 03, and a step of 6 bytes and 300 lines as
06 FF 00 2D.
Worked example
This example is constructed by hand from the rules above, with no Python this old running it. It is a three-line function, leaving out the code that follows its last statement.
1 def f(a):
2 x = a
3 return x
| Offset | Bytes | Instruction |
|---|---|---|
| 0 | 7C 00 00 | LOAD_FAST 0 |
| 3 | 7D 01 00 | STORE_FAST 1 |
| 6 | 7C 01 00 | LOAD_FAST 1 |
| 9 | 53 | RETURN_VALUE |
co_firstlineno is 1. The first statement is on line 2 at offset 0, so
the first pair is 00 01. The second statement starts at offset 6, six bytes
on and one line on, so the table is 00 01 06 01.
Reading it back, the first pair moves to offset 0, line 2, and the second to offset 6, line 3. Offsets 0 to 5 are line 2 and offsets from 6 are line 3.