Title: [C API] Add `PyTupleWriter` API · Issue #139888 · python/cpython · GitHub
Open Graph Title: [C API] Add `PyTupleWriter` API · Issue #139888 · python/cpython
X Title: [C API] Add `PyTupleWriter` API · Issue #139888 · python/cpython
Description: Feature or enhancement Hi, Creating a tuple with the current C API has multiple issues: PyTuple_SetItem() and PyTuple_SET_ITEM() modify an immutable tuple. PyTuple_New() creates an incomplete object: items are set to NULL. This is bad: c...
Open Graph Description: Feature or enhancement Hi, Creating a tuple with the current C API has multiple issues: PyTuple_SetItem() and PyTuple_SET_ITEM() modify an immutable tuple. PyTuple_New() creates an incomplete objec...
X Description: Feature or enhancement Hi, Creating a tuple with the current C API has multiple issues: PyTuple_SetItem() and PyTuple_SET_ITEM() modify an immutable tuple. PyTuple_New() creates an incomplete objec...
Opengraph URL: https://github.com/python/cpython/issues/139888
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"[C API] Add `PyTupleWriter` API","articleBody":"# Feature or enhancement\n\nHi,\n\nCreating a tuple with the current C API has multiple issues:\n\n* `PyTuple_SetItem()` and `PyTuple_SET_ITEM()` modify an **immutable** tuple.\n* `PyTuple_New()` creates an incomplete object: items are set to `NULL`. This is bad:\n * https://github.com/capi-workgroup/problems/issues/56 \n * https://github.com/capi-workgroup/api-evolution/issues/36\n* `PyTuple_New()` tracks directly the tuple in the garbage collector. For example, `gc.get_objects()` gives access to the incomplete tuple. Using the tuple, like calling `repr(tuple)`, can crash Python.\n* [`_PyTuple_Resize()`](https://docs.python.org/dev/c-api/tuple.html#c._PyTuple_Resize) is private which is surprising for a documented API. It stays private because it has issues.\n* `_PyTuple_Resize()` modifies an **immutable** tuple.\n* `_PyTuple_Resize()` must not be used of the refcount is greater than `1`: the API is fragile.\n\nI propose adding a new efficient `PyTupleWriter` API: work on a temporary \"writer\" object, and then call `Finish()` on it to get the tuple.\n\nI already proposed a similar API in 2023: [`_PyTupleBuilder`](https://github.com/python/cpython/pull/107139). Since that, Python C API got the [`PyUnicodeWriter` API](https://docs.python.org/dev/c-api/unicode.html#pyunicodewriter) and the [`PyBytesWriter` API](https://docs.python.org/dev/c-api/bytes.html#pybyteswriter) which are efficient writers for `str` and `bytes` objects, and the C API Working Group was created. The proposed API is now public and allocates the structure on the heap memory to hide the implementation details (the structure).\n\nMark Shannon asked if it would be possible to work on a list and then convert the list to a tuple, but it's [less efficient](https://github.com/python/cpython/issues/107137#issuecomment-1689718305). Tuples are commonly used in Python, and so creating a tuple should be efficient.\n\nMark Shannon also tried to initialize tuple items to `None` instead of `NULL` in `PyTuple_New()`. His attempt failed because of implementation issues. Also, this change only fix some of the issues that I listed, not all of them.\n\nAn alternative is to fill a C array of Python objects, call the new `PyTuple_FromArray()`, and then call `Py_DECREF()` on the array items. It requires to allocate and deallocate an array, and call `Py_DECREF()` on items. It can be less efficient.\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-139891\n* gh-140129\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/vstinner","@type":"Person","name":"vstinner"},"datePublished":"2025-10-10T07:43:53.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":7},"url":"https://github.com/139888/cpython/issues/139888"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:3d0aa549-3a43-5bac-61e7-1e05c6ccb8c9 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | C3DA:22BD75:BCCC8E:10888AC:696A631C |
| html-safe-nonce | fefd5ae536ccd9e4b9e019e5b87f3bbb1314eb118db627b2e67dd0fc35821175 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDM0RBOjIyQkQ3NTpCQ0NDOEU6MTA4ODhBQzo2OTZBNjMxQyIsInZpc2l0b3JfaWQiOiI1NTYxNDc3ODg4MzUyMDg0NzY0IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | a30789b4270b3e4683d5d26bf0da27a15877609282efc32c510b2945ffdaf519 |
| hovercard-subject-tag | issue:3501760658 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/139888/issue_layout |
| twitter:image | https://opengraph.githubassets.com/0ffd805dc15518415405c3e936dd8d18dd07a34252cb854590b25ce4dc5161fe/python/cpython/issues/139888 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/0ffd805dc15518415405c3e936dd8d18dd07a34252cb854590b25ce4dc5161fe/python/cpython/issues/139888 |
| og:image:alt | Feature or enhancement Hi, Creating a tuple with the current C API has multiple issues: PyTuple_SetItem() and PyTuple_SET_ITEM() modify an immutable tuple. PyTuple_New() creates an incomplete objec... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | vstinner |
| hostname | github.com |
| expected-hostname | github.com |
| None | 9b7735a184970dd9333b2cbe036c8f3c0a9108c64aaa93827c5a64fc70993392 |
| turbo-cache-control | no-preview |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 87cbd411c2982752221b5751d583a515b23bf5fa |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width