wxPython4.1.1 Python3.8 locale wxAssertionError

On Windows 10, wxPython 4.1.1, Python 3.8

Getting the following error when trying to initialize image bmp = wx.Image(“image.png”)

File "app.py", line 628, in __init__
wx._core.wxAssertionError: C++ assertion "strcmp(setlocale(0, 0), "C") == 0" failed at ..\..\src\common\intl.cpp(1694) in wxLocale::GetInfo(): You probably called setlocale() directly instead of using wxLocale and now there is a mismatch between C/C++ and Windows locale.
Things are going to break, please only change locale by creating wxLocale objects to avoid this!

This is only happening with windows Region = “Spanish (Latin America)”

image

Changing to “Spanish Mexico” fixes the issue.

In fact, what I noticed is that the issue only happens when Windows Region language is set to a language that doesn’t exit in wxWidgets: interface/wx/language.h File Reference

So, “Spanish (Dominican Republic)” works, but “Spanish (Cuba)” doesn’t. Ecuador works, Equatorial Guinea doesn’t.

Setting the locale during the initialization like below

class MyApp(wx.App):
    def OnInit(self):
        self.locale = wx.Locale(wx.LANGUAGE_DEFAULT)

causes another problem - it breaks all the “standard” (non-wx) python functions that are using standard locale (such as datetime.strptime for example). Basically those functions are failing with ValueError: unknown locale: en-US due to the fact that wxPython seems to follow “windows way” in setting the locale and is using “-” hyphen in the locale name. The “sandard” python functions are using “linux way” with “_” underscore in the locale name.

The only (ugly and hacky) workaround that I found looks like this:

  1. On startup, override the python locale to “C” locale. Interestingly, this step is only required in Python 3.8 (python 3.7 is already returning locale (None, None) on startup)
import locale
locale.setlocale(locale.LC_ALL,'C')
  1. Then in wx.App, override the InitLocale to prevent wxPython from setting the locale in “windows way”. This is only required with wxPython4.1.1 (4.0.4 works without it, apparently it doesn’t try to initialize the locale in any way and it remains “c” locale).
    def InitLocale(self):
        self.ResetLocale()

Is there anything I’m missing? As mentioned, issue is only happening with certain language settings.

The full code to reproduce

import wx
import locale

class mainFrame(wx.Frame):
    def __init__(self,parent):
        wx.Frame.__init__(self,parent,-1,"title")
        bmp = wx.Image("image.png") # this will fail if win locale is Spanish Latin America
        print('locale during: %s'% (locale.getlocale(),)) # this will fail with ValueError if you try to initialize wx.Locale in the wx.app OnInit

class MyApp(wx.App):
    def OnInit(self):
        w = mainFrame(None)
        w.Show()
        return True

def main():
    app = MyApp(False)
    app.MainLoop()

if __name__ == '__main__':
    main()

See https://github.com/wxWidgets/Phoenix/issues/1637.

My “solution” has so far been to stay on 4.0.7post2.

Yep, the change that started causing this problem turned up in Python 3.8.

I’ve been thinking of trying to simplify InitLocale much like this, instead of trying to bring the C runtime and wxWIdgets into sync with what the system thinks should be the default. I’ve made the following change in a test app that shows the problem for me, and it works fine, but I’m in a US locale and don’t need to do anything related to the locale other than this.

So for those that are using non-US locales, especially if you also need to create a wx.Locale for access to message catalogs, or other locale specific things please try the experiment and let us know how it goes.

The experiment is to simply add the following method to your wx.App-derived class. If you also need to set an explicit wx.Locale then do so after the code above, and remember to hold on to the reference to the wx.Local object.

    def InitLocale(self):
        import sys
        if sys.platform.startswith('win') and sys.version_info > (3,8):
            import locale
            locale.setlocale(locale.LC_ALL, "C")

Please reply with how it works for you, and if it doesn’t help then also reply with any clues you may have discovered.

I get a similar issue with wxPython v4.1.1 while v4.0.7post2 works fine.
time.strptime throws ValueError after initializing the locale. This is Python 3.8 on Windows 10.

import time, wx
app=wx.App()
time.strptime("Nov 17 10:00:01", "%b %d %H:%M:%S")  # works fine
wx.GetLocale().SysName                              # 'en_US'
locale = wx.Locale(wx.LANGUAGE_DEFAULT)
time.strptime("Nov 17 10:00:01", "%b %d %H:%M:%S")  # ValueError: unknown locale: en-US
wx.GetLocale().SysName                              # 'en-US'

The function InitLocale is working for me!

Thank you for the workaround - I was really struggling on how to solve this.

I am using Python 3.8, wxPython 4.1.1 in Windows10.
This is my region set up:

This problem is over 15 months old and still exists in python3.9.13 with wxPython4.1.1

Will there be any solution soon?

I used to struggle with this a lot, but I haven’t had any issue since upgrading to a wxPython 4.1.2 alpha with Python 3.10. I’m using 4.1.2a1.dev5293+b2199e29 which is wxWidgets 3.1.5 based. It is, at least for my purposes and on MSW, production quality despite the alpha designation.

The latest alphas are based on wxWidgets 3.2.0 RC1 and may be a bit more rough around the edges.

downgrade to wxpython 4.0.6 and pandas 1.1.5, in windows 7