From: matthew a. <ma...@ca...> - 2005-03-05 01:10:38
|
Hi, A few months back I gave a little report to matplotlib-users on using matplotlib on Japanese Windows. There were several issues that I managed to find workarounds for. I wanted to give an update on the font_manager.py bug. This bug is still in matplotlib (as of CVS earlier today) and causes a matplotlib import to throw a WindowsError exception (ErrNo 234). This has happened to me on every Windows 2000 Japanese PC I've tried it on, including PCs which had a pretty fresh installs of Win2K. (It may also happen on Japanese WinXP, I haven't tried it.) In other words, it's a showstopper. And it happens even without py2exe. A bit of google searching turned up a couple of *.jp blogs mentioning the error. The workaround I suggested last Novemeber works (see my message quoted below), but it's a bit of a kludge. I dug a bit into the bug today and discovered it's actually a side-effect of what appears to be a Microsoft Win32 API registry bug. _winreg uses RegQueryInfoKey to ask for the maximum length of all the subkeys in the fonts registry key. Then _winreg creates a buffer of that length (plus 1 for NULL termination) and uses RegEnumValue to grab the subkey, but for some fonts Windows returns ERROR_MORE_DATA (234) indicating that the buffer size is too small. There are at least 3 fonts that trigger it, which seem to be standard on Japanese Win2k. To make a long story short, _winreg is failing to deal with some Japanese font registry keys, and throwing the WindowsError (ErrNo 234). A good workaround is to add a "try / except WindowsError: pass" around the _winreg.EnumValue() stanza inside the for loop. From my testing, for a system with 93 fonts, this should skip the 3 troublesome fonts and catalog the rest. My apologies that I cannot provide a patch or a simple test case at this time, but I hope this report is useful. Cheers, Matthew. p.s. It may be there are ways to work around this bug in _winreg, which I think would be the better place to do it. E.g. by using RegEnumValue to query the subkey size instead of RegQueryInfoKey. But I haven't isolated a simple test case yet, apart from "import matplotlib" on Japanese Win2k. Here is the code fragment: MSFontDirectories = [ r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts', r'SOFTWARE\Microsoft\Windows\CurrentVersion\Fonts'] ... def win32InstalledFonts(directory=None, fontext='ttf'): """Search for fonts in the specified font directory, or use the system directories if none given. A list of TrueType fonts are returned by default with AFM fonts as an option. """ import _winreg if directory is None: directory = win32FontDirectory() key, items = None, {} for fontdir in MSFontDirectories: try: local = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, fontdir) except OSError: continue if not local: return glob.glob(os.path.join(directory, '*.'+fontext)) try: for j in range(_winreg.QueryInfoKey(local)[1]): key, direc, any = _winreg.EnumValue( local, j) if not os.path.dirname(direc): direc = os.path.join(directory, direc) direc = os.path.abspath(direc).lower() if direc[-4:] == '.'+fontext: items[direc] = 1 return items.keys() finally: _winreg.CloseKey(local) return None On 1/11/2004 3:32 PM, matthew arnison wrote: > I thought I'd mention some small isuues I found with using py2exe to deploy matplotlib 0.63.2 on Japanese Windows 2000. > > [...snip...] > > * font_manager.py throws an exception, I suspect to do with Japanese font names or font directory names: > > File "c:\Python23\lib\site-packages\matplotlib\font_manager.py", line 111, in > win32InstalledFonts > key, direc, any = _winreg.EnumValue( local, j) > WindowsError: [Errno 234] > > from this site: > > http://www.google.com.au/search?q=cache:B8BlgKwVYxcJ:www.cubelab.com/ymasuda/python/index_jp.html+matplotlib+local+None+windowserror&hl=en > > I found a workaround to add > > local = None > > at line 107 of font_manager.py to give this: > > for fontdir in MSFontDirectories: > try: > local = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, fontdir) > except OSError: > continue > > local = None > > if not local: > return glob.glob(os.path.join(directory, '*.'+fontext)) |
From: John H. <jdh...@ac...> - 2005-03-05 02:41:00
|
>>>>> "matthew" == matthew arnison <ma...@ca...> writes: matthew> To make a long story short, _winreg is failing to deal matthew> with some Japanese font registry keys, and throwing the matthew> WindowsError (ErrNo 234). A good workaround is to add a matthew> "try / except WindowsError: pass" around the matthew> _winreg.EnumValue() stanza inside the for loop. From my matthew> testing, for a system with 93 fonts, this should skip the matthew> 3 troublesome fonts and catalog the rest. matthew> My apologies that I cannot provide a patch or a simple matthew> test case at this time, but I hope this report is useful. Hi Matthew -- thanks for your efforts on this. I have to honestly say that I don't have a lot of time to work on this bug -- I don't know enough about Japanese fonts or the windows registry. None of the other matplotlib developers seem to have taken up the banner either. If you can provide a patch that fixes or works around the bug, I'd be very happy to include it. I could work figure out the appropriate patch by reading your email closely, but I don't have a good environment to test it, so it would be more efficient if you simply submitted a patch that has your try/except workaround until we can come up with something better. Thanks! JDH |