🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

Deprecation of locale.getdefaultlocale breaks POSIX compatibility on Windows platform #130796

Closed

Description

@Wedge009

Bug report

Bug description:

Follow-up to #90817.

In summary, without getdetfaultlocale, tools that rely on POSIX locales cannot reliably get the same information from getlocale or setlocale on Windows.

For example, Linux will return something like 'en_AU'. But on Windows, getlocale will return something like 'English_Australia'.

CPython versions tested on:

3.12, 3.13

Operating systems tested on:

Windows, Linux

Linked PRs

Activity

  1. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Mar 3, 2025
  2. added
    type-featureA feature request or enhancement
    and removed
    type-bugAn unexpected behavior, bug, or error
    on Mar 3, 2025
  3. picnixz commented on Mar 3, 2025

    @picnixz
    Member

    I'm afraid that this issue is too late because the ship has already sailed. I don't remember well which alternatives there are for that kind of issue so I'll tag @vstinner who was responsible for the original patch. However, I doubt that we would reinstate locale.getdefaultlocale (or we would do something else).

    EDIT: Actually it seems to only be deprecated and planned for removal in 3.15: #111187.

  4. added
    pendingThe issue will be closed if no feedback is provided
    on Mar 3, 2025
  5. Wedge009 commented on Mar 3, 2025

    @Wedge009
    Author

    I don't think I - or others - was asking for a reinstatement, just a viable alternative for the cases where POSIX locales are expected for use with other tools such as gettext.

    And yes, removal is planned for 3.15, hence the discussion now. As noted in wesnoth/wesnoth#9972 (comment), it's difficult to know how to work around the removal of getdefaultlocale when we don't know what future plans are - if any - for any replacement functionality.

  6. vstinner commented on Mar 3, 2025

    @vstinner
    Member

    On my Windows 11 VM, getlocale() returns a "POSIX" locale as expected:

    vstinner@WIN C:\victor\python\main>python
    Python 3.14.0a5+ (heads/pr/130452-dirty:6a5dc1a8ba6, Feb 26 2025, 17:30:51) [MSC v.1943 32 bit (Intel)] on win32
    >>> import locale
    >>> locale.getlocale()
    ('fr_FR', 'cp1252')
    >>> locale.setlocale(locale.LC_CTYPE, None)
    'French_France.1252'

    Can you please elaborate your issue? What are the results of locale.getlocale() and locale.setlocale(locale.LC_CTYPE, None)?

  7. Wedge009 commented on Mar 3, 2025

    @Wedge009
    Author

    It's as I described above and in #90817 (comment).

    Python 3.13.2 (tags/v3.13.2:4f8bb39, Feb  4 2025, 15:23:48) [MSC v.1942 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license()" for more information.
    import locale
    locale.getlocale()
    ('English_Australia', '1252')
    locale.setlocale(locale.LC_CTYPE)
    'English_Australia.1252'
    locale.getdefaultlocale()
    
    Warning (from warnings module):
      File "<pyshell#3>", line 1
    DeprecationWarning: 'locale.getdefaultlocale' is deprecated and slated for removal in Python 3.15. Use setlocale(), getencoding() and getlocale() instead.
    ('en_AU', 'cp1252')

    @shineworld reported something similar in #90817 (comment)

    @Elvish-Hunter reports the same in wesnoth/wesnoth#9972 (comment)

  8. 2trvl commented on Mar 6, 2025

    @2trvl
    Contributor

    The reason why POSIX compatibility breaks is this:

    The windows_locale dictionary is only used by the locale.getdefaultlocale() function and this function is deprecated: it will be removed in Python 3.15.

    Windows 22H2, Python 3.13.1:

    >>> locale.setlocale(locale.LC_CTYPE)
    'English_United States.1252'
    
    >>> locale.getlocale()
    ('English_United States', '1252')
    
    >>> locale.getdefaultlocale()
    ('en_US', 'cp1252')
  9. 2trvl commented on Mar 7, 2025

    @2trvl
    Contributor

    I would like to know how can I find out the system locale for LC_TIME without using defaultlocale?

    >>> locale.getdefaultlocale(["LC_TIME"])
    ('ru_RU', 'UTF-8')
    
    >>> locale.setlocale(locale.LC_TIME)
    'C'
    
    >>> locale.getlocale(locale.LC_TIME)
    (None, None)

    Apparently I have no other option than to change the interpreter locale:

    >>> locale.setlocale(locale.LC_TIME, "")
    'ru_RU.UTF-8'
    
    >>> locale.getlocale(locale.LC_TIME)
    ('ru_RU', 'UTF-8')

    It is generally a bad idea to call setlocale() in some library routine, since as a side effect it affects the entire program. Saving and restoring it is almost as bad: it is expensive and affects other threads that happen to run before the settings have been restored.

    I see that the original reason for removal is the use of non-ASCII characters in locale. Do you think this is a common case?

    If fixing the problem is difficult or impossible, perhaps it is worth introducing a similar function called getpreferredlocale?

  10. StanFromIreland commented on May 17, 2025

    @StanFromIreland
    Member

    The windows_locale dictionary is well out of date anyway (and is no longer updated from what I can tell), so keeping the function is not great either. The dictionary itself is not deprecated, and so you should be able to use it. If we do want to provide this functionality on windows, it should be better though out.

    I was unable to find any windows API that returns the POSIX format.

  11. 6 remaining items

  12. gpshead commented on Dec 20, 2025

    @gpshead
    Member

    I added the 3.15 release blocker labels as if we don't solve this for 3.15 we should stop the deprecation.

  13. chris-eibl commented on Dec 22, 2025

    @chris-eibl
    Member

    Related: #82986 and #67613 (where @eryksun presented a rough prototype to auto-populate locale_alias, #67613 (comment)).

  14. added a commit that references this issue on Dec 22, 2025
  15. vstinner commented on Dec 22, 2025

    @vstinner
    Member

    I wasn't aware that locale.getdefaultlocale() is the only way to get a POSIX-like locale name on Windows when I deprecated the function. I didn't know neither that there are users of the "read the locale from environment variables" feature. There is no good replacement for these features, so I wrote #143069 to undeprecate locale.getdefaultlocale().

  16. vstinner commented on Dec 22, 2025

    @vstinner
    Member

    FYI getdefaultlocale() was not removed yet because we are aware of these issues.

  17. malemburg commented on Dec 22, 2025

    @malemburg
    Member

    Whereas locale.getlocale() internally calls C setlocale(LC_CTYPE, NULL) which returns German_Austria for me.

    This is then further processed via locale.normalize() which does a lookup in locale_alias

    cpython/Lib/locale.py

    Line 763 in 786f464

    The locale_alias table maps lowercase alias names to C locale names

    which fails for German_Austria and all the other examples given in this issue, but succeeds for e.g.

    'french_france':                        'fr_FR.ISO8859-1',
    'german_germany':                       'de_DE.ISO8859-1',
    

    Thus, @vstinner gets fr_FR above and @malemburg gets de_DE in #90817 (comment).

    I suppose we could make locale.getlocale() work for this use case by adding the Windows locale names to the locale_alias table.

    Apparently I have no other option than to change the interpreter locale:

    locale.setlocale(locale.LC_TIME, "")
    'ru_RU.UTF-8'

    locale.getlocale(locale.LC_TIME)
    ('ru_RU', 'UTF-8')

    This is why I had added locale.getdefaultlocale() a long while ago: I did not want to break libraries which rely on other custom local settings by calling setlocale(LC_ALL, ""), since this then applies to the whole process. Doing so at random times can be especially problematic for embedded Python interpreters.

    Nowadays, CPython does call setlocale(LC_CTYPE, NULL); during startup and that was what triggered the deprecation of locale.setdefaultlocale(). However, you are right in that the call only configures the LC_CTYPE part of the locale settings, not the other ones, such as LC_TIME. We should probably change the startup code to call setlocale(LC_ALL, "") instead - as recommended by the C lib docs.

    So I guess two changes would be necessary to fix this situation:

    • add the Windows locale names to the alias table

    • have Python init all locale parts during startup

    or we leave locale.getdefaultlocale() around, but given that it's purpose has been superseded, I don't think that's a good idea.

  18. vstinner commented on Dec 23, 2025

    @vstinner
    Member

    setlocale(LC_CTYPE, "") is called by Python during startup: in _Py_SetLocaleFromEnv(LC_CTYPE) which is called by _PyPreConfig_Write().

  19. added a commit that references this issue on Dec 23, 2025
  20. vstinner commented on Dec 23, 2025

    @vstinner
    Member

    I close the issue. The function is no longer deprecated in Python 3.15.

  21. added 2 commits that reference this issue on Jun 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.15bugs and security fixespendingThe issue will be closed if no feedback is providedrelease-blockerstdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions