gcsupport.md
1> **Источник:** https://python-all.ru/3.10/c-api/gcsupport.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Поддержка циклической сборки мусора89Поддержка Python обнаружения и сбора мусора, связанного с циклическими ссылками, требует поддержки со стороны объектных типов, которые являются «контейнерами» для других объектов, которые также могут быть контейнерами. Типы, которые не хранят ссылок на другие объекты или хранят только ссылки на атомарные типы (например, числа или строки), не нуждаются в явной поддержке сборки мусора.1011Чтобы создать контейнерный тип, поле [`tp_flags`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_flags) объекта типа должно включать [`Py_TPFLAGS_HAVE_GC`](https://python-all.ru/3.10/c-api/typeobj.html#Py_TPFLAGS_HAVE_GC) и предоставлять реализацию обработчика [`tp_traverse`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_traverse). Если экземпляры типа являются изменяемыми, также должна быть предоставлена реализация [`tp_clear`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_clear).1213#### `Py_TPFLAGS_HAVE_GC`1415Объекты с типом, у которого установлен этот флаг, должны соответствовать правилам, описанным здесь. Для удобства такие объекты будут называться контейнерными объектами.1617Конструкторы контейнерных типов должны соответствовать двум правилам:18191. Память для объекта должна выделяться с помощью [`PyObject_GC_New()`](https://python-all.ru/3.10/c-api/gcsupport.html#c.PyObject_GC_New) или [`PyObject_GC_NewVar()`](https://python-all.ru/3.10/c-api/gcsupport.html#c.PyObject_GC_NewVar).202. Как только все поля, которые могут содержать ссылки на другие контейнеры, будут инициализированы, необходимо вызвать [`PyObject_GC_Track()`](https://python-all.ru/3.10/c-api/gcsupport.html#c.PyObject_GC_Track).2122Аналогично, деаллокатор объекта должен соответствовать такой же паре правил:23241. Перед тем как поля, ссылающиеся на другие контейнеры, станут недействительными, должен быть вызван [`PyObject_GC_UnTrack()`](https://python-all.ru/3.10/c-api/gcsupport.html#c.PyObject_GC_UnTrack).252. Память объекта должна быть освобождена с помощью [`PyObject_GC_Del()`](https://python-all.ru/3.10/c-api/gcsupport.html#c.PyObject_GC_Del).2627 > **Предупреждение**28 >29 > Если тип добавляет Py\_TPFLAGS\_HAVE\_GC, то он *должен* реализовать как минимум обработчик [`tp_traverse`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_traverse) или явно использовать его из своего подкласса или подклассов.30 >31 > При вызове [`PyType_Ready()`](https://python-all.ru/3.10/c-api/type.html#c.PyType_Ready) или некоторых API, которые вызывают его косвенно, таких как [`PyType_FromSpecWithBases()`](https://python-all.ru/3.10/c-api/type.html#c.PyType_FromSpecWithBases) или [`PyType_FromSpec()`](https://python-all.ru/3.10/c-api/type.html#c.PyType_FromSpec), интерпретатор автоматически заполнит поля [`tp_flags`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_flags), [`tp_traverse`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_traverse) и [`tp_clear`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_clear), если тип наследуется от класса, реализующего протокол сборщика мусора, и дочерний класс *не* включает флаг [`Py_TPFLAGS_HAVE_GC`](https://python-all.ru/3.10/c-api/typeobj.html#Py_TPFLAGS_HAVE_GC).3233#### `TYPE *PyObject_GC_New(TYPE, PyTypeObject *type)`3435Аналогично [`PyObject_New()`](https://python-all.ru/3.10/c-api/allocation.html#c.PyObject_New), но для контейнерных объектов с установленным флагом [`Py_TPFLAGS_HAVE_GC`](https://python-all.ru/3.10/c-api/typeobj.html#Py_TPFLAGS_HAVE_GC).3637#### `TYPE *PyObject_GC_NewVar(TYPE, PyTypeObject *type, Py_ssize_t size)`3839Аналогично [`PyObject_NewVar()`](https://python-all.ru/3.10/c-api/allocation.html#c.PyObject_NewVar), но для контейнерных объектов с установленным флагом [`Py_TPFLAGS_HAVE_GC`](https://python-all.ru/3.10/c-api/typeobj.html#Py_TPFLAGS_HAVE_GC).4041#### `TYPE *PyObject_GC_Resize(TYPE, PyVarObject *op, Py_ssize_t newsize)`4243Изменяет размер объекта, выделенного с помощью [`PyObject_NewVar()`](https://python-all.ru/3.10/c-api/allocation.html#c.PyObject_NewVar). Возвращает изменённый объект или `NULL` в случае ошибки. *op* ещё не должен отслеживаться сборщиком.4445#### `void PyObject_GC_Track(PyObject *op)`4647*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*4849Добавляет объект *op* в набор контейнерных объектов, отслеживаемых сборщиком. Сборщик может запускаться в неожиданные моменты, поэтому объекты должны быть корректны во время отслеживания. Эту функцию следует вызывать, когда все поля, за которыми следит обработчик [`tp_traverse`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_traverse), станут корректны, обычно ближе к концу конструктора.5051#### `int PyObject_IS_GC(PyObject *obj)`5253Возвращает ненулевое значение, если объект реализует протокол сборщика мусора, иначе возвращает 0.5455Объект не может отслеживаться сборщиком мусора, если эта функция возвращает 0.5657#### `int PyObject_GC_IsTracked(PyObject *op)`5859*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable) начиная с версии 3.9.*6061Возвращает 1, если тип объекта *op* реализует протокол GC и *op* в данный момент отслеживается сборщиком мусора, и 0 в противном случае.6263Это аналог функции Python [`gc.is_tracked()`](https://python-all.ru/3.10/library/gc.html#gc.is_tracked).6465Новое в версии 3.9.6667#### `int PyObject_GC_IsFinalized(PyObject *op)`6869*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable) начиная с версии 3.9.*7071Возвращает 1, если тип объекта *op* реализует протокол GC и *op* уже был финализирован сборщиком мусора, и 0 в противном случае.7273Это аналог функции Python [`gc.is_finalized()`](https://python-all.ru/3.10/library/gc.html#gc.is_finalized).7475Новое в версии 3.9.7677#### `void PyObject_GC_Del(void *op)`7879*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*8081Освобождает память, выделенную объекту через [`PyObject_GC_New()`](https://python-all.ru/3.10/c-api/gcsupport.html#c.PyObject_GC_New) или [`PyObject_GC_NewVar()`](https://python-all.ru/3.10/c-api/gcsupport.html#c.PyObject_GC_NewVar).8283#### `void PyObject_GC_UnTrack(void *op)`8485*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*8687Удаляет объект *op* из набора контейнерных объектов, отслеживаемых сборщиком. Обратите внимание, что [`PyObject_GC_Track()`](https://python-all.ru/3.10/c-api/gcsupport.html#c.PyObject_GC_Track) можно снова вызвать для этого объекта, чтобы вернуть его в набор отслеживаемых объектов. Деструктор (обработчик [`tp_dealloc`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_dealloc)) должен вызывать это для объекта до того, как какие-либо поля, используемые обработчиком [`tp_traverse`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_traverse), станут недействительными.8889Изменено в версии 3.8: Макросы `_PyObject_GC_TRACK()` и `_PyObject_GC_UNTRACK()` были удалены из публичного C API.9091Обработчик [`tp_traverse`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_traverse) принимает параметр-функцию следующего типа:9293#### `typedef int (*visitproc)(PyObject *object, void *arg)`9495*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*9697Тип функции обхода, передаваемой обработчику [`tp_traverse`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_traverse). Функцию следует вызывать с объектом для обхода в качестве *object* и третьим параметром обработчика [`tp_traverse`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_traverse) в качестве *arg*. Ядро Python использует несколько функций обхода для реализации обнаружения циклического мусора; не ожидается, что пользователям потребуется писать собственные функции обхода.9899Обработчик [`tp_traverse`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_traverse) должен иметь следующий тип:100101#### `typedef int (*traverseproc)(PyObject *self, visitproc visit, void *arg)`102103*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*104105Функция обхода для объекта-контейнера. Реализации должны вызывать функцию *visit* для каждого объекта, непосредственно содержащегося в *self*; параметрами *visit* являются содержащийся объект и значение *arg*, переданное обработчику. Функция *visit* не должна вызываться с аргументом-объектом `NULL`. Если *visit* возвращает ненулевое значение, его следует немедленно вернуть.106107Чтобы упростить написание обработчиков [`tp_traverse`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_traverse), предоставляется макрос [`Py_VISIT()`](https://python-all.ru/3.10/c-api/gcsupport.html#c.Py_VISIT). Для использования этого макроса реализация [`tp_traverse`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_traverse) должна называть свои аргументы точно *visit* и *arg*:108109#### `void Py_VISIT(PyObject *o)`110111Если *o* не равно `NULL`, вызвать колбэк *visit* с аргументами *o* и *arg*. Если *visit* возвращает ненулевое значение, вернуть его. Используя этот макрос, обработчики [`tp_traverse`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_traverse) выглядят так:112113```c114static int115my_traverse(Noddy *self, visitproc visit, void *arg)116{117 Py_VISIT(self->foo);118 Py_VISIT(self->bar);119 return 0;120}121```122123Обработчик [`tp_clear`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_clear) должен иметь тип [`inquiry`](https://python-all.ru/3.10/c-api/gcsupport.html#c.inquiry) или `NULL`, если объект неизменяем.124125#### `typedef int (*inquiry)(PyObject *self)`126127*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*128129Удаляет ссылки, которые могли создать циклические ссылки. Неизменяемые объекты не обязаны определять этот метод, поскольку они никогда не могут напрямую создавать циклические ссылки. Обратите внимание, что объект после вызова этого метода должен оставаться корректным (нельзя просто вызвать [`Py_DECREF()`](https://python-all.ru/3.10/c-api/refcounting.html#c.Py_DECREF) для ссылки). Сборщик вызовет этот метод, если обнаружит, что этот объект участвует в циклической ссылке.130131## Управление состоянием сборщика мусора132133C-API предоставляет следующие функции для управления запусками сборки мусора.134135#### `Py_ssize_t PyGC_Collect(void)`136137*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*138139Выполняет полную сборку мусора, если сборщик мусора включён. (Обратите внимание, что [`gc.collect()`](https://python-all.ru/3.10/library/gc.html#gc.collect) запускает её безусловно.)140141Возвращает количество собранных + недостижимых объектов, которые не могут быть собраны. Если сборщик мусора отключён или уже выполняет сборку, немедленно возвращает `0`. Ошибки во время сборки мусора передаются в [`sys.unraisablehook`](https://python-all.ru/3.10/library/sys.html#sys.unraisablehook). Эта функция не вызывает исключений.142143#### `int PyGC_Enable(void)`144145*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable) начиная с версии 3.10.*146147Включает сборщик мусора: аналогично [`gc.enable()`](https://python-all.ru/3.10/library/gc.html#gc.enable). Возвращает предыдущее состояние: 0 – отключён, 1 – включён.148149Новое в версии 3.10.150151#### `int PyGC_Disable(void)`152153*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable) начиная с версии 3.10.*154155Отключает сборщик мусора: аналогично [`gc.disable()`](https://python-all.ru/3.10/library/gc.html#gc.disable). Возвращает предыдущее состояние: 0 – отключён, 1 – включён.156157Новое в версии 3.10.158159#### `int PyGC_IsEnabled(void)`160161*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable) начиная с версии 3.10.*162163Запрашивает состояние сборщика мусора: аналогично [`gc.isenabled()`](https://python-all.ru/3.10/library/gc.html#gc.isenabled). Возвращает текущее состояние: 0 – отключён, 1 – включён.164165Новое в версии 3.10.166