https://github.com/python/cpython/commit/4c497b1a09fe59c81fd330147ed12d954487a8ee
commit: 4c497b1a09fe59c81fd330147ed12d954487a8ee
branch: main
author: Cody Maloney <[email protected]>
committer: cmaloney <[email protected]>
date: 2026-11-03T12:49:50-08:00
summary:

gh-159446: Avoid TypeError on FileIO construction (#159480)

FileIO can be constructed off a string or an integer file descriptor.
It used PyLong_AsInt first to check "is this an integer". That raised a
TypeError when passed a string which would then be silenced. Proactively
check if it is a number with _PyIndex_Check saving instructions in the
common filename path.

Callgrind, instructions per `FileIO(path).readall()` + `close()` of a
111-byte file:

| Build            | base   | this change |
|------------------|-------:|------------:|
| PGO+LTO          | 10,641 | 8,918 |
| -O3, no PGO      | 14,154 | 12,016 |

pyperf, the same on a 182-byte file, PGO+LTO, 4 interleaved rounds of
10 processes:

| Benchmark      | base | this change              |
|----------------|:-------:|:---------------------:|
| fileio_readall | 3.71 us | 3.62 us: 1.02x faster |

Co-Authored-By: Claude Opus 5.5 <[email protected]>

files:
M Modules/_io/fileio.c

diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
index e5cd7aca5de2f17..732eb28e51ba8c1 100644
--- a/Modules/_io/fileio.c
+++ b/Modules/_io/fileio.c
@@ -1,6 +1,7 @@
 /* Author: Daniel Stutzbach */
 
 #include "Python.h"
+#include "pycore_abstract.h"      // _PyIndex_Check()
 #include "pycore_fileutils.h"     // _Py_BEGIN_SUPPRESS_IPH
 #include "pycore_object.h"        // _PyObject_GC_UNTRACK()
 #include "pycore_pyerrors.h"      // _PyErr_ChainExceptions1()
@@ -300,14 +301,17 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, 
const char *mode,
             return -1;
         }
     }
-    fd = PyLong_AsInt(nameobj);
-    if (fd < 0) {
-        if (!PyErr_Occurred()) {
-            PyErr_SetString(PyExc_ValueError,
-                            "negative file descriptor");
-            return -1;
+    if (_PyIndex_Check(nameobj)) {
+        fd = PyLong_AsInt(nameobj);
+        if (fd < 0) {
+            if (!PyErr_Occurred()) {
+                PyErr_SetString(PyExc_ValueError,
+                                "negative file descriptor");
+                return -1;
+            }
+            /* Failed to convert; try other paths. */
+            PyErr_Clear();
         }
-        PyErr_Clear();
     }
 
     if (fd < 0) {

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to