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:
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:
continuelocal = None
if not local:
return glob.glob(os.path.join(directory, '*.'+fontext))