- How to Check if a File Exists in Python: Try/Except, Path, and IsFile
- Table of Contents
- Problem Introduction
- Solutions
- Check if a File Exists with a Try Block
- Check if a File Exists with OS Path
- Check if a File Exists with a Path Object
- Performance
- A Little Recap
- Recent Posts
- About Me
- Legal
- Longest Active Series
- Pythonic way to check if a file exists? [duplicate]
- 5 Answers 5
How to Check if a File Exists in Python: Try/Except, Path, and IsFile
Once again, welcome to the How to Python series. In this collection, we explore programming problems that have quick solutions in Python. In this edition, we explore a few ways to check if a file exists in Python, so let’s dive in!
Table of Contents
Problem Introduction
Recently, I was looking for a way to persist some user settings of an app to a file. For instance, I wanted to save options like font size, background color, etc. Naturally, I settled on a simple mapping format like YAML, but I could have just as easily used a CSV which we already know how to parse. Unfortunately, the configuration file wouldn’t be backwards compatible without some support in the software. In other words, if the configuration file didn’t exist, I would need to assume some original preset values. Otherwise, I would pull the data from the configuration file. Fortunately, I did my research and came up with a solution. The plan was to check to see if the configuration file existed. If it did, the program would read from it and populate the necessary fields. Otherwise, the program would lean back on some arbitrary preset values. To do that though, I had to find a way to verify the existence of a file. As it turns out, there are plenty of ways to do that in Python.
Solutions
- Check if a file exists with a try/except block (Python 2+)
- Check if a file exists using os.path (Python 2+)
- Check if a file exists using the Path object (Python 3.4+)
Of course, it’s up to us to determine which solution is the best for us!
Check if a File Exists with a Try Block
Up first on the list is a simple try-except block. In this scenario, we would attempt to open our file in the try block. If the file fails to open, we run the preset values. For example:
try: with open('/path/to/file', 'r') as fh: # Load configuration file values except FileNotFoundError: # Keep preset values
In this example, we try to open the file using a with statement. If successful, we can load our configuration file values. Otherwise, the open command will throw an error that we catch in the except block. At that point, we keep our preset values and move on.
To be honest, this solution is perhaps the simplest and most robust, but the FileNotFoundError is an update from Python 3. You’ll have more trouble with catching an IOError in Python 2.
Also, it’s worth noting that we use a with statement in this example. As an alternative, we can open the file directly. We just have to remember to close it when we’re done:
Check if a File Exists with OS Path
Another option is to skip error handling altogether and directly verify that the path exists. For example:
import os exists = os.path.isfile('/path/to/file') if exists: # Load configuration file values else: # Keep presets
Of course, the drawback here is the race condition from line 2 to line 4. If for some reason the configuration file gets deleted between line 2 and line 4, then the script will crash. If that’s not a risk in your application, then this solution is great.
That said, I’ll emphasize this issue again because I did get a bit of pushback on it in the past:
Checking if a file exists and opening that file are two different operations in this example. They would need to be one atomic operation to avoid a race condition.
Check if a File Exists with a Path Object
If you’re obsessed with object-oriented programming like me, then maybe this solution is for you. As of Python 3.4, we can wrap our file reference in an object which brings along a host of new functionality. For example:
from pathlib import Path config = Path('/path/to/file') if config.is_file(): # Load configuration file values else: # Keep presets
In addition, this new object representation allows us to use our original try-except block:
try: absolute_path = config.resolve() # Load configuration file values except FileNotFoundError: # Keep presets
Of course, we may not need all this functionality. After all, if reading the contents is the goal, then the first option is probably the best.
Performance
While we’ve already shared all the solutions, it may be important for our application to look at performance as well. To do that, we’ll leverage the timeit library. First, however, we need to generate a few strings:
setup = """ import os from pathlib import Path """ try_except = """ try: with open('/path/to/file', 'r') as fh: pass except FileNotFoundError: pass """ os_isfile = """ exists = os.path.isfile('/path/to/file') """ path_lib = """ config = Path('/path/to/file') if config.is_file(): pass """
With the strings ready to go, we’ll run this test twice: once where the file exists and again when it doesn’t, respectively.
>>> timeit.timeit(stmt=try_except, setup=setup) 25.758140300000036 >>> timeit.timeit(stmt=os_isfile, setup=setup) 23.302945200000067 >>> timeit.timeit(stmt=path_lib, setup=setup) 36.851380800000015
Normally, we would use the repeat function to try to calculate some sort of lower bound for each function, but it was just way too slow. Feel free to try it and share the results.
For the existing file tests, we’ll have to change the paths in each of the strings above, so they include an existing file. As a result, some of these solutions are significantly slower:
timeit.timeit(stmt=try_except, setup=setup) 220.5547474 >>> timeit.timeit(stmt=os_isfile, setup=setup) 194.13558469999975 >>> timeit.timeit(stmt=path_lib, setup=setup) 208.86859360000017
Here, we can see all of the solutions are quite a bit slower when dealing with an existing file. That said, it seems the os solution is the fastest in both circumstances. Of course, it does have the race condition drawback, so be sure to take that into account when choosing one of these methods.
For reference, all tests were completed using Windows 10 and Python 3.7.3. If you want to learn more about Python performance testing, check out my article titled How to Performance Test Python Code.
A Little Recap
Using the methods above, we have several options to check if a file exists in Python:
# Brute force with a try-except block try: with open('/path/to/file', 'r') as fh: pass except FileNotFoundError: pass # Leverage the OS package import os exists = os.path.isfile('/path/to/file') # Wrap the path in an object for enhanced functionality from pathlib import Path config = Path('/path/to/file') if config.is_file(): pass
For the purposes of this tutorial, we were only interested in files. However, these solutions can be adapted to verify the existences of directories and symbolic links, so don’t be afraid to play around. That’s the beauty of Python!
At any rate, thanks for taking the time to check out this article. If it’s your first time here and you found this article helpful, why not subscribe to The Renegade Coder? Alternatively, you can always hop on the mailing list and decide to become a member at a later time.
In the meantime, you may benefit from my list of Python Code Snippets for Everyday Problems.
If you’re not convinced, check out some the following related posts:
Finally, feel free to browse the following related books:
How to Python (42 Articles)—Series Navigation
The How to Python tutorial series strays from the usual in-depth coding articles by exploring byte-sized problems in Python. In this series, students will dive into unique topics such as How to Invert a Dictionary, How to Sum Elements of Two Lists, and How to Check if a File Exists.
Each problem is explored from the naive approach to the ideal solution. Occasionally, there’ll be some just-for-fun solutions too. At the end of every article, you’ll find a recap full of code snippets for your own use. Don’t be afraid to take what you need!
If you’re not sure where to start, I recommend checking out our list of Python Code Snippets for Everyday Problems. In addition, you can find some of the snippets in a Jupyter notebook format on GitHub,
If you have a problem of your own, feel free to ask. Someone else probably has the same problem. Enjoy How to Python!
Jeremy grew up in a small town where he enjoyed playing soccer and video games, practicing taekwondo, and trading Pokémon cards. Once out of the nest, he pursued a Bachelors in Computer Engineering with a minor in Game Design. After college, he spent about two years writing software for a major engineering company. Then, he earned a master’s in Computer Science and Engineering. Today, he pursues a PhD in Engineering Education in order to ultimately land a teaching gig. In his spare time, Jeremy enjoys spending time with his wife, playing Overwatch and Phantasy Star Online 2, practicing trombone, watching Penguins hockey, and traveling the world.
Recent Posts
Life is a gift worth celebrating even after that life is gone. Let me share a little bit of my experience with one of these celebrations.
Part of the PhD journey is conducting a study which you can write about for a dissertation. Right now, I’m in the middle of data collection, and I wanted to share how it was going.
About Me
Welcome to The Renegade Coder, a coding curriculum website run by myself, Jeremy Grifski. If you like what you see, consider subscribing to my newsletter. Right now, new subscribers will receive a copy of my Python 3 Beginner Cheat Sheet. If newsletters aren’t your thing, there are at least 4 other ways you can help grow The Renegade Coder. I appreciate the support!
Legal
The Renegade Coder is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to Amazon.com.
Longest Active Series
Pythonic way to check if a file exists? [duplicate]
Actual duplicate question: Safely create a file if and only if it does not exist with python. In Python 3.3+, use the ‘x’ flag when open() ing a file to avoid race conditions.
5 Answers 5
To check if a path is an existing file:
Return True if path is an existing regular file. This follows symbolic links, so both islink() and isfile() can be true for the same path.
Of course, you can get into a race condition where the file doesn’t exist when you check, but springs into existence before you can create it. Extremely unlikely, but possible.
This will return true if a directory exists by the given name, in which case a subsequent creation of the file will fail.
I think you are thinking of os.path.exists, which returns True if the path exists (i.e. is a file or a directory). As shown above, os.path.isfile returns True when the path is a regular file.
This answer is outdated. On Python 3.4+ use pathlib , like this: Path(«path/to/file»).is_file() if you want to check that it’s a file and that it exists or Path(«path/to/file»).exists() if you only want to know that it exists (but might be a directory).
Instead of os.path.isfile , suggested by others, I suggest using os.path.exists , which checks for anything with that name, not just whether it is a regular file.
if not os.path.exists(filename): file(filename, 'w').close()
The latter will create the file if it exists, but not otherwise. It will, however, fail if the file exists, but you don’t have permission to write to it. That’s why I prefer the first solution.
For Python 3 need to replace file with open : if not os.path.exists(filename): open(filename, «w+»).close()
It seems to me that all other answers here (so far) fail to address the race-condition that occurs with their proposed solutions.
Any code where you first check for the files existence, and then, a few lines later in your program, you create it, runs the risk of the file being created while you weren’t looking and causing you problems (or you causing the owner of «that other file» problems).
If you want to avoid this sort of thing, I would suggest something like the following (untested):
import os def open_if_not_exists(filename): try: fd = os.open(filename, os.O_CREAT | os.O_EXCL | os.O_WRONLY) except OSError, e: if e.errno == 17: print e return None else: raise else: return os.fdopen(fd, 'w')
This should open your file for writing if it doesn’t exist already, and return a file-object. If it does exists, it will print «Ooops» and return None (untested, and based solely on reading the python documentation, so might not be 100% correct).