PEP 626:Guarantee stability of line table during release and define API for out-of-process tools. (#1555)

* Guarantee stability of line table during release and implement API for out-of-process tools.
This commit is contained in:
Mark Shannon 2020-08-10 14:33:33 +01:00 committed by GitHub
parent c2c08f612c
commit 8dd402b7a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 58 additions and 1 deletions

View File

@ -183,6 +183,57 @@ Access to the ``f_lineno`` attribute of frame objects through C API functions is
Accessing ``f_lineno`` directly through the underlying data structure is forbidden.
Out of process debuggers and profilers
''''''''''''''''''''''''''''''''''''''
Out of process tools, such as py-spy [1]_, cannot use the C-API, and must parse the line number table themselves.
Although the line number table format may change without warning,
it will not change during a release unless absolutely necessary for a bug fix.
To reduce the work required to implement these tools, the following C struct and utility functions are provided.
Note that these functions are not part of the C-API, so will be need to be linked into any code that needs to use them.
::
typedef struct addressrange {
int ar_start;
int ar_end;
int ar_line;
int opaque1;
void *opaque2;
} PyCodeAddressRange;
void PyLineTable_InitAddressRange(char *linetable, int firstlineno, PyCodeAddressRange *range);
int PyLineTable_NextAddressRange(PyCodeAddressRange *range);
int PyLineTable_PreviousAddressRange(PyCodeAddressRange *range);
``PyLineTable_InitAddressRange`` initializes the ``PyCodeAddressRange`` struct from the line number table and first line number.
``PyLineTable_NextAddressRange`` advances the range to the next entry, returning non-zero if valid.
``PyLineTable_PreviousAddressRange`` retreats the range to the previous entry, returning non-zero if valid.
For example, the following code prints out all the address ranges:
::
void print_address_ranges(char *linetable, int firstlineno)
{
PyCodeAddressRange range;
PyLineTable_InitAddressRange(linetable, firstlineno, &range);
while (PyLineTable_NextAddressRange(&range)) {
printf("Bytecodes from %d (inclusive) to %d (exclusive) ",
range.start, range.end);
if (range.line < 0) {
/* line < 0 means no line number */
printf("have no line number\n");
}
else {
printf("have line number %d\n", range.line);
}
}
}
Performance Implications
========================
@ -194,7 +245,7 @@ Code with long sequences of ``pass`` statements will probably become a bit slowe
Reference Implementation
========================
Under development.
https://github.com/markshannon/cpython/tree/new-linetable-format-version-2
Copyright
=========
@ -202,6 +253,12 @@ Copyright
This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.
References
==========
.. [1] py-spy: Sampling profiler for Python programs
(https://github.com/benfred/py-spy)
..