[Spambayes-checkins] SF.net SVN: spambayes: [3165] trunk/spambayes/spambayes/storage.py

montanaro at users.sourceforge.net montanaro at users.sourceforge.net
Mon Oct 22 04:42:47 CEST 2007


Revision: 3165
          http://spambayes.svn.sourceforge.net/spambayes/?rev=3165&view=rev
Author:   montanaro
Date:     2007-10-21 19:42:47 -0700 (Sun, 21 Oct 2007)

Log Message:
-----------
Isolate the code to safely write pickles so it can be used elsewhere in the
system.  From Dave Abrahams (SF patch 1816240).

Modified Paths:
--------------
    trunk/spambayes/spambayes/storage.py

Modified: trunk/spambayes/spambayes/storage.py
===================================================================
--- trunk/spambayes/spambayes/storage.py	2007-10-22 02:29:03 UTC (rev 3164)
+++ trunk/spambayes/spambayes/storage.py	2007-10-22 02:42:47 UTC (rev 3165)
@@ -85,6 +85,36 @@
 NO_UPDATEPROBS = False   # Probabilities will not be autoupdated with training
 UPDATEPROBS = True       # Probabilities will be autoupdated with training
 
+def safe_pickle(filename, value, protocol=0):
+    '''Store value as a pickle without creating corruption'''
+
+    # Be as defensive as possible.  Always keep a safe copy.
+    tmp = filename + '.tmp'
+    fp = None
+    try: 
+        fp = open(tmp, 'wb') 
+        pickle.dump(value, fp, protocol) 
+        fp.close() 
+    except IOError, e: 
+        if options["globals", "verbose"]: 
+            print >> sys.stderr, 'Failed update: ' + str(e)
+        if fp is not None: 
+            os.remove(tmp) 
+        raise
+    try:
+        # With *nix we can just rename, and (as long as permissions
+        # are correct) the old file will vanish.  With win32, this
+        # won't work - the Python help says that there may not be
+        # a way to do an atomic replace, so we rename the old one,
+        # put the new one there, and then delete the old one.  If
+        # something goes wrong, there is at least a copy of the old
+        # one.
+        os.rename(tmp, filename)
+    except OSError:
+        os.rename(filename, filename + '.bak')
+        os.rename(tmp, filename)
+        os.remove(filename + '.bak')
+    
 class PickledClassifier(classifier.Classifier):
     '''Classifier object persisted in a pickle'''
 
@@ -141,31 +171,7 @@
         if options["globals", "verbose"]:
             print >> sys.stderr, 'Persisting',self.db_name,'as a pickle'
 
-        # Be as defensive as possible; keep always a safe copy.
-        tmp = self.db_name + '.tmp'
-        try: 
-            fp = open(tmp, 'wb') 
-            pickle.dump(self, fp, PICKLE_TYPE) 
-            fp.close() 
-        except IOError, e: 
-            if options["globals", "verbose"]: 
-                print >> sys.stderr, 'Failed update: ' + str(e)
-            if fp is not None: 
-                os.remove(tmp) 
-            raise
-        try:
-            # With *nix we can just rename, and (as long as permissions
-            # are correct) the old file will vanish.  With win32, this
-            # won't work - the Python help says that there may not be
-            # a way to do an atomic replace, so we rename the old one,
-            # put the new one there, and then delete the old one.  If
-            # something goes wrong, there is at least a copy of the old
-            # one.
-            os.rename(tmp, self.db_name)
-        except OSError:
-            os.rename(self.db_name, self.db_name + '.bak')
-            os.rename(tmp, self.db_name)
-            os.remove(self.db_name + '.bak')
+        safe_pickle(self.db_name, self, PICKLE_TYPE)
 
     def close(self):
         # we keep no resources open - nothing to do


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.


More information about the Spambayes-checkins mailing list