Issue #25182: The stdprinter (used as sys.stderr before the io module is
imported at startup) now uses the backslashreplace error handler.
diff --git a/Misc/NEWS b/Misc/NEWS
index 487eea1..55f4e40 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -11,6 +11,9 @@
 Core and Builtins
 -----------------
 
+- Issue #25182: The stdprinter (used as sys.stderr before the io module is
+  imported at startup) now uses the backslashreplace error handler.
+
 - Issue #25131: Make the line number and column offset of set/dict literals and
   comprehensions correspond to the opening brace.
 
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index 1b18410..a836cb3 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -372,8 +372,11 @@
 static PyObject *
 stdprinter_write(PyStdPrinter_Object *self, PyObject *args)
 {
+    PyObject *unicode;
+    PyObject *bytes = NULL;
     char *str;
     Py_ssize_t n;
+    int _errno;
 
     if (self->fd < 0) {
         /* fd might be invalid on Windows
@@ -383,13 +386,27 @@
         Py_RETURN_NONE;
     }
 
-    /* encode Unicode to UTF-8 */
-    if (!PyArg_ParseTuple(args, "s", &str))
+    if (!PyArg_ParseTuple(args, "U", &unicode))
         return NULL;
 
-    n = _Py_write(self->fd, str, strlen(str));
+    /* encode Unicode to UTF-8 */
+    str = PyUnicode_AsUTF8AndSize(unicode, &n);
+    if (str == NULL) {
+        PyErr_Clear();
+        bytes = _PyUnicode_AsUTF8String(unicode, "backslashreplace");
+        if (bytes == NULL)
+            return NULL;
+        if (PyBytes_AsStringAndSize(bytes, &str, &n) < 0) {
+            Py_DECREF(bytes);
+            return NULL;
+        }
+    }
+
+    n = _Py_write(self->fd, str, n);
+    _errno = errno;
+    Py_XDECREF(bytes);
     if (n == -1) {
-        if (errno == EAGAIN) {
+        if (_errno == EAGAIN) {
             PyErr_Clear();
             Py_RETURN_NONE;
         }