Maintaining accurate f.name through rename operation in Python w/o dropping lock
<p>I have a file which I'm atomically replacing in Python, while trying to persistently retain a lock.</p>

<p>(Yes, I'm well aware that this will wreak havoc on any other programs waiting for a lock on the file unless they check for the directory entry pointing to a new inode after they actually receive their lock; that check is happening in practice).</p>

<pre><code>import os, os.path, tempfile, fcntl

def replace_file(f, new_text):
    f_dir = os.path.dirname(f.name)
    with tempfile.NamedTemporaryFile(dir=f_dir) as temp_file:
         temp_file.write(new_text)
         temp_file.flush()
         os.fsync(temp_file.fileno())
         dest_file = os.fdopen(os.dup(temp_file.fileno()), 'r+b')
         fcntl.flock(dest_file.fileno(), fcntl.LOCK_EX)
         os.rename(temp_file.name, f.name)
         temp_file.delete = False
    # ...and after more paranoia, like fsync()ing the directory it's in...
    return dest_file

f = open('/tmp/foo', 'w')
f = replace_file(f, "new string")
print f.name # name is &lt;fdup&gt;, not /tmp/foo
</code></pre>

<p>I'm hard-pressed to find a workaround for this that doesn't involve dropping the lock even temporarily after the rename has taken place.</p>

<p>A simplicity-focused solution is to use an entirely separate lockfile with a different name (ie. <code>&lt;filename&gt;.lck</code>).</p>

<ul>
<li>Using a separate lockfile means that the code performing the write-and-rename operation doesn't need to be involved in locking at all, as the rename operation doesn't interact with the lock.</li>
<li>Using a separate lockfile avoids the need to jump through hoops to avoid breaking clients which might find that they've successfully grabbed a lock, but hold it on a now-deleted file rather than the version currently bound to the directory.</li>
</ul>

python