Skip to content

Commit 177d921

Browse files
authored
bpo-34485, Windows: LC_CTYPE set to user preference (GH-8988)
On Windows, the LC_CTYPE is now set to the user preferred locale at startup: _Py_SetLocaleFromEnv(LC_CTYPE) is now called during the Python initialization. Previously, the LC_CTYPE locale was "C" at startup, but changed when calling setlocale(LC_CTYPE, "") or setlocale(LC_ALL, ""). pymain_read_conf() now also calls _Py_SetLocaleFromEnv(LC_CTYPE) to behave as _Py_InitializeCore(). Moreover, it doesn't save/restore the LC_ALL anymore. On Windows, standard streams like sys.stdout now always use surrogateescape error handler by default (ignore the locale).
1 parent 315877d commit 177d921

File tree

3 files changed

+13
-19
lines changed

3 files changed

+13
-19
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
On Windows, the LC_CTYPE is now set to the user preferred locale at startup.
2+
Previously, the LC_CTYPE locale was "C" at startup, but changed when calling
3+
setlocale(LC_CTYPE, "") or setlocale(LC_ALL, "").

Modules/main.c

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,25 +1280,18 @@ pymain_read_conf_impl(_PyMain *pymain, _PyCoreConfig *config,
12801280
}
12811281

12821282

1283-
/* Read the configuration, but initialize also the LC_CTYPE locale:
1284-
enable UTF-8 mode (PEP 540) and/or coerce the C locale (PEP 538) */
1283+
/* Read the configuration and initialize the LC_CTYPE locale:
1284+
enable UTF-8 mode (PEP 540) and/or coerce the C locale (PEP 538). */
12851285
static int
12861286
pymain_read_conf(_PyMain *pymain, _PyCoreConfig *config,
12871287
_PyCmdline *cmdline)
12881288
{
12891289
int init_utf8_mode = Py_UTF8Mode;
12901290
_PyCoreConfig save_config = _PyCoreConfig_INIT;
1291-
char *oldloc = NULL;
12921291
int res = -1;
12931292

1294-
oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL));
1295-
if (oldloc == NULL) {
1296-
pymain->err = _Py_INIT_NO_MEMORY();
1297-
goto done;
1298-
}
1299-
1300-
/* Reconfigure the locale to the default for this process */
1301-
_Py_SetLocaleFromEnv(LC_ALL);
1293+
/* Set LC_CTYPE to the user preferred locale */
1294+
_Py_SetLocaleFromEnv(LC_CTYPE);
13021295

13031296
int locale_coerced = 0;
13041297
int loops = 0;
@@ -1386,10 +1379,6 @@ pymain_read_conf(_PyMain *pymain, _PyCoreConfig *config,
13861379

13871380
done:
13881381
_PyCoreConfig_Clear(&save_config);
1389-
if (oldloc != NULL) {
1390-
setlocale(LC_ALL, oldloc);
1391-
PyMem_RawFree(oldloc);
1392-
}
13931382
Py_UTF8Mode = init_utf8_mode ;
13941383
return res;
13951384
}

Python/pylifecycle.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ static _LocaleCoercionTarget _TARGET_LOCALES[] = {
343343
static const char *
344344
get_stdio_errors(void)
345345
{
346+
#ifndef MS_WINDOWS
346347
const char *ctype_loc = setlocale(LC_CTYPE, NULL);
347348
if (ctype_loc != NULL) {
348349
/* surrogateescape is the default in the legacy C and POSIX locales */
@@ -362,6 +363,10 @@ get_stdio_errors(void)
362363
}
363364

364365
return "strict";
366+
#else
367+
/* On Windows, always use surrogateescape by default */
368+
return "surrogateescape";
369+
#endif
365370
}
366371

367372
#ifdef PY_COERCE_C_LOCALE
@@ -751,11 +756,8 @@ _Py_InitializeCore(PyInterpreterState **interp_p,
751756
(and the input configuration is read only). */
752757
_PyCoreConfig config = _PyCoreConfig_INIT;
753758

754-
#ifndef MS_WINDOWS
755-
/* Set up the LC_CTYPE locale, so we can obtain the locale's charset
756-
without having to switch locales. */
759+
/* Set LC_CTYPE to the user preferred locale */
757760
_Py_SetLocaleFromEnv(LC_CTYPE);
758-
#endif
759761

760762
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
761763
if (_PyCoreConfig_Copy(&config, src_config) >= 0) {

0 commit comments

Comments
 (0)