The Cost of Dynamism (was Re: Pyhon 2.x or 3.x, which is faster?)

Chris Angelico rosuav at gmail.com
Wed Mar 23 02:28:45 EDT 2016


On Wed, Mar 23, 2016 at 5:07 PM, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> Fortunately, not all such "bugs" are of equal severity. In this case, there
> are two failure modes. Consider a *false positive* bug: we think the file
> exists when it actually doesn't.
>
> if os.path.exists(filename):
>     os.unlink(filename)  # some other process does this
>     open(filename)
>
>
> This is probably bad. At best, we get some sort of unhandled exception.

Yes - and it's exactly why it's not worth bothering with the 'exists'
check. Your code would end up looking like this:

if os.path.exists(filename):
    try:
        open(filename)
    except FileNotFoundError:
        # file got deleted out from under you
else:
    # file doesn't exist

Which is exactly why error handling (whether with structured
exceptions or error codes) is better than LBYL for anything involving
the file system, or shared resources and concurrency, or anything with
a potential TOCTTOU discrepancy.

All the other situations (apart from renaming) are handled the same
way - sure, the consequences aren't as serious, but it's just as easy
to use the same technique everywhere. I don't know of a cross-platform
way to rename without overwriting, but the "mv" command on my system
has a --no-clobber option, and the underlying rename system call seems
to have a non-standard flags parameter that can be set to
RENAME_NOREPLACE to prevent overwriting. This is generally the way to
fix it; it's only in the system call that this can actually be done
reliably (hence things like temp file creation are done with flags to
the file-open syscall).

ChrisA



More information about the Python-list mailing list