<div class="gmail_quote">On Thu, Mar 12, 2009 at 4:09 PM, &quot;Martin v. Löwis&quot; <span dir="ltr">&lt;<a href="mailto:martin@v.loewis.de">martin@v.loewis.de</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
So when you select &quot;Save&quot; in your application, would you like the data<br>
to be saved, or would you accept that they get lost? If the latter,<br>
what kind of interaction would you perform with your application to<br>
indicate that you *do* want the data to appear on disk?<br>
</blockquote></div><br>I accept that if the computer crashes at just the wrong moment as I click Save, my changes will not actually be Saved.  No amount of diligence in the implementation of close() can prevent that since the computer can crash before the program calls close().<br>
<br>I oppose applications that lose or corrupt both my new save and my *previous* save if the computer crashes at the wrong moment.  That would cause me to lose not only my most recent changes (an inconvenience), but also all the work I have ever done on the file (a major headache for anyone who doesn&#39;t make regular backups).<br>
<br>However, defaulting to calling fsync() when closing a file will:<br>1) Cripple performance for the many applications that don&#39;t need it (e.g., temporary files)<br>2) Fail to prevent data loss for applications that use the truncate-and-rewrite paradigm for saving<br>
<br>Consider the following example:<br><br>with open(&#39;mysavefile&#39;, &#39;w&#39;) as f:<br>    f.write(data)<br>    f.flush()<br>    os.fsync(f.fileno()) <br>    f.close()<br><br>If the system crashes after the call to open(), but before the call to fsync(), then both the old and the new mysavefile may be gone.<br>
<br>Since needing to safely replace a file with new data is a moderately common task, perhaps it would be useful to have a convenience class that looks like a file, but takes care of the ugly details behind-the-scenes?  Something vaguely like this flawed and untested class:<br>
<br>class open_for_safe_replacement(file): # needs a better name<br>    def __init__(self, path, flags):<br>        if &#39;w&#39; not in flags:<br>            raise RuntimeError, &#39;Writing without writing?&#39;<br>        self.path = path<br>
        self.tmp_name = some_function_that_generates_a_safe_temporary_filename() # good luck<br>        file.__init__(self.tmp_name, flags)<br><br>    def close(self):<br>        self.flush()<br>        os.fsync(self.fileno())<br>
        self.close()<br>        os.rename(self.tmp_name, self.path) # won&#39;t work on Windows :-(<br>        <br>then we could simply:<br><br>with appropriate_module.open_for_safe_replacement(&#39;mysavefile&#39;, &#39;w&#39;):<br>
    f.write(data)<br><blockquote style="margin: 1.5em 0pt;">--<br>
Daniel Stutzbach, Ph.D.<br>
President, <a href="http://stutzbachenterprises.com">Stutzbach Enterprises, LLC</a>
</blockquote>