Skip to content

Commit 73f9de3

Browse files
[3.15] gh-158126: Avoid creating AttributeError for optional Pickler attribute lookups (GH-158148) (GH-160251)
(cherry picked from commit e60a9da) Co-authored-by: Lazizbek Ergashev <lazerg2@gmail.com>
1 parent af13832 commit 73f9de3

2 files changed

Lines changed: 26 additions & 4 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Speed up :func:`pickle.dumps` and creating a :class:`pickle.Pickler` by
2+
avoiding the creation of an :exc:`AttributeError` when looking up the
3+
optional ``reducer_override`` and ``dispatch_table`` attributes.

‎Modules/_pickle.c‎

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4846,6 +4846,25 @@ persistent_id(PyObject *self, PyObject *obj)
48464846
Py_RETURN_NONE;
48474847
}
48484848

4849+
static PyObject *Pickler_getattr(PyObject *self, PyObject *name);
4850+
4851+
/* Like PyObject_GetOptionalAttr(), but avoids creating an AttributeError
4852+
for a missing attribute. Must not be used for "persistent_id". */
4853+
static int
4854+
pickler_get_optional_attr(PicklerObject *self, PyObject *name,
4855+
PyObject **result)
4856+
{
4857+
if (Py_TYPE(self)->tp_getattro == Pickler_getattr) {
4858+
*result = _PyObject_GenericGetAttrWithDict((PyObject *)self, name,
4859+
NULL, 1);
4860+
if (*result != NULL) {
4861+
return 1;
4862+
}
4863+
return PyErr_Occurred() ? -1 : 0;
4864+
}
4865+
return PyObject_GetOptionalAttr((PyObject *)self, name, result);
4866+
}
4867+
48494868
static int
48504869
dump(PickleState *state, PicklerObject *self, PyObject *obj)
48514870
{
@@ -4867,8 +4886,8 @@ dump(PickleState *state, PicklerObject *self, PyObject *obj)
48674886
Py_XSETREF(self->persistent_id, tmp);
48684887

48694888
/* Cache the reducer_override method, if it exists. */
4870-
if (PyObject_GetOptionalAttr((PyObject *)self, &_Py_ID(reducer_override),
4871-
&tmp) < 0) {
4889+
if (pickler_get_optional_attr(self, &_Py_ID(reducer_override),
4890+
&tmp) < 0) {
48724891
goto error;
48734892
}
48744893
Py_XSETREF(self->reducer_override, tmp);
@@ -5148,8 +5167,8 @@ _pickle_Pickler___init___impl(PicklerObject *self, PyObject *file,
51485167
self->fast_memo = NULL;
51495168

51505169
if (self->dispatch_table == NULL) {
5151-
if (PyObject_GetOptionalAttr((PyObject *)self, &_Py_ID(dispatch_table),
5152-
&self->dispatch_table) < 0) {
5170+
if (pickler_get_optional_attr(self, &_Py_ID(dispatch_table),
5171+
&self->dispatch_table) < 0) {
51535172
goto error;
51545173
}
51555174
}

0 commit comments

Comments
 (0)