Hi, I'm Paul Finn

I'm a full stack web developer with a preference for Python. I also enjoy discussions on entrepreneurship and software marketing.


Handcrafted in Portsmouth, NH

Django Goodness, Delivered To Your Inbox

I'm writing a book about Django development. Subscribe to my small mailing list to get first drafts, along with Django development tips and tricks.

← Return to blog home

Using Python: How To Check If A File Exists

If you find yourself doing any kind of disk-based I/O with Python, you'll undoubtedly come across the need to verify that a file exists before continuing to read/write against it. There are multiple ways to do this but also some things you should watch for.

You may initially discover the os.path.exists() method, but keep in mind that this will yield True for both files and directories. This lack of specificity could easily introduce bugs and data loss if not expected.

#Returns true for directories, not just files
>>> print os.path.exists('/this/is/a/dir')
True

If you want to zero-in on just files, stick to os.path.isfile() method. Remember that something could happen to a file in the time between checking that it exists and actually preforming read/write operations against it. This approach will not lock the file in any way and therefore your code can become vulnerable to "time of check to time of use" (TOCTTOU) bugs.

#Returns true for directories, not just files
if os.path.isfile('my_settings.dat'):
    #...
    with open('my_settings.dat') as file:
       pass  #Potential for unhandled exception
True

Yes, that's a real thing. Wikipedia has an article on TOCTTOU bugs, along with an example of how symlinks can be used by an attacker. I encourage you to read it.

Raising exceptions is considered to be an acceptable, and Pythonic, approach for flow control in your program. Consider handling missing files with IOErrors, rather than if statements. In this situation, an IOError exception will be raised if the file exists but the user does not have read permissions.

try:
    with open('my_settings.dat') as file:
        pass
except IOError as e:
    print "Unable to open file" #Does not exist OR no read permissions

I hope this was helpful. If you have comments or feedback, please email me at pvfinn at gmail.com. Thanks!

← Return to blog home