[Moving to the devel list.]

Here's a patch for font_manager.py to close opened files. Could
somebody review the patch? As I mentioned earlier, I don't understand
why cPickle/pickle is not imported at the top level, so I'm hesitant
to check this in without review.

Index: lib/matplotlib/font_manager.py
===================================================================
--- lib/matplotlib/font_manager.py	(revision 3046)
+++ lib/matplotlib/font_manager.py	(working copy)
@@ -39,6 +39,10 @@
 from matplotlib import ft2font
 from matplotlib import rcParams, get_home, get_configdir
 
+try:
+    import cPickle as pickle
+except ImportError:
+    import pickle
 
 verbose = matplotlib.verbose
 
@@ -446,9 +450,16 @@
         else: seen[fname] = 1
         if fontext == 'afm':
             try:
-                font = afm.AFM(file(fpath))
+                fh = file(fpath)
+            except:
+                verbose.report("Could not open font file %s" % fpath)
+                continue
+            try:
+                font = afm.AFM(fh)
+                fh.close()
             except RuntimeError:
-                verbose.report("Could not open font file %s"%fpath)
+                fh.close()
+                verbose.report("Could not parse font file %s"%fpath)
                 continue
             prop = afmFontProperty(font)
         else:
@@ -765,6 +776,25 @@
                             fnames.append(fname)
     return fnames
 
+def pickle_dump(data, filename):
+    """Equivalent to pickle.dump(data, file(filename, 'w'))
+    but closes the file to prevent filehandle leakage."""
+    fh = file(filename, 'w')
+    try:
+        pickle.dump(data, fh)
+    finally:
+        fh.close()
+
+def pickle_load(filename):
+    """Equivalent to pickle.load(file(filename, 'r'))
+    but closes the file to prevent filehandle leakage."""
+    fh = file(filename, 'r')
+    try:
+        data = pickle.load(fh)
+    finally:
+        fh.close()
+    return data
+
 class FontManager:
     """
     On import, the FontManager creates a dictionary of TrueType
@@ -820,18 +850,13 @@
             print >> sys.stderr, 'Moving old ttfcache location "%s" to new location "%s"'%(oldcache, ttfcache)
             shutil.move(oldcache, ttfcache)
 
-        try:
-            import cPickle as pickle
-        except ImportError:
-            import pickle
-
         def rebuild():
             self.ttfdict = createFontDict(self.ttffiles)
-            pickle.dump(self.ttfdict, file(ttfcache, 'w'))
+            pickle_dump(self.ttfdict, ttfcache)
             verbose.report(cache_message % ttfcache)
 
         try:
-            self.ttfdict = pickle.load(file(ttfcache))
+            self.ttfdict = pickle_load(ttfcache)
         except:
             rebuild()
         else:
@@ -972,11 +997,6 @@
         return self.defaultFont
 
     def _get_afm_font_dict(self):
-        try:
-            import cPickle as pickle
-        except ImportError:
-            import pickle
-        
         cache_message = "Saving AFM font cache for PS and PDF backends to %s.\n" \
                         "Delete this file to have matplotlib rebuild the cache."
         
@@ -989,21 +1009,21 @@
             # ZapfDingbats.
             afmcache = os.path.join(get_configdir(), 'pdfcorefont.cache')
             try:
-                fontdict = pickle.load(file(afmcache))
+                fontdict = pickle_load(afmcache)
             except:
                 afmpath = os.path.join(rcParams['datapath'],'fonts','pdfcorefonts')
                 afmfiles = findSystemFonts(afmpath, fontext='afm')
                 fontdict = createFontDict(afmfiles, fontext='afm')
-                pickle.dump(fontdict, file(afmcache, 'w'))
+                pickle_dump(fontdict, afmcache)
                 verbose.report(cache_message % afmcache)
         else:
             # Load all available AFM fonts
             afmcache = os.path.join(get_configdir(), '.afmfont.cache')
             try:
-                fontdict = pickle.load(file(afmcache))
+                fontdict = pickle_load(afmcache)
             except:
                 fontdict = createFontDict(self.afmfiles, fontext='afm')
-                pickle.dump(fontdict, file(afmcache, 'w'))
+                pickle_dump(fontdict, afmcache)
                 verbose.report(cache_message % afmcache)
         
         return fontdict
Jouni K. Seppänen <[EMAIL PROTECTED]> writes:

> I fixed another filehandle leak in the pdf backend, so here's a more
> complete patch. There are also several cases of file(...) being passed
> to pickle.dump or pickle.load in font_manager.py. I was going to take
> care of these by writing some utility functions, but I started
> wondering why the import of cPickle or pickle is done only within
> methods of FontManager and not at the top level. Are there some
> platforms where neither is available, or what is the rationale?

-- 
Jouni K. Seppänen
http://www.iki.fi/jks
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Reply via email to