The Short Answer
To check whether a file exists, use os.path.isfile() from the standard library. It returns True when the path names an existing regular file and False otherwise. It never raises an error for a missing path.
Paths are relative to the folder the program runs in (the current working directory), unless you pass an absolute path such as /home/ada/notes.txt or C:\Users\Ada\notes.txt.
The rest of this page covers the other ways to ask the question, how they differ, and the case where you should not ask it at all.
os.path.exists vs isfile vs isdir
The os.path module has three related checks, and they answer slightly different questions:
| Function | Returns True when the path is |
|---|---|
os.path.exists(p) | anything that exists: a file, a directory, or a working symlink |
os.path.isfile(p) | an existing regular file |
os.path.isdir(p) | an existing directory |
The difference shows up as soon as a directory is involved:
Output:
reports True False True
reports/summary.txt True True False
reports/old.txt False False False
os.path.exists("reports") is True even though reports is a folder. If your code is about to read the path as a file, exists is the wrong check: a directory would pass it, and open("reports") would then fail (with IsADirectoryError on Linux and macOS, PermissionError on Windows). Pick isfile when you mean a file and isdir when you mean a folder.
Two more details about these three os.path functions:
- A symlink is followed. A link that points to a real file counts as a file; a broken link (its target is gone) returns
Falsefrom all three. - If Python is not allowed to look inside a folder, the check returns
Falserather than raisingPermissionError.Falsemeans "not found or not reachable", not strictly "does not exist".
Checking With pathlib
pathlib is the object-oriented path API in the standard library, and most new code uses it. A Path object has the same three checks as methods:
Path.exists(), Path.is_file() and Path.is_dir() behave like os.path.exists, isfile and isdir. The / operator joins path parts with the right separator for the operating system, so folder / "summary.txt" works on Windows, macOS and Linux alike. See file handling for reading and writing through Path objects.
Which one should you use? If the rest of your code already passes Path objects around, stay with pathlib. If you are working with plain strings and os functions, os.path.isfile is just as correct. They give the same answers.
Why Checking First Can Be the Wrong Move
The most common reason to check whether a file exists is to open it afterwards:
import os
if os.path.isfile("config.txt"):
with open("config.txt") as f: # the file might be gone by now
settings = f.read()
else:
settings = ""
This has a gap. Between the isfile() call and the open() call, another program, another thread, or the user can delete or rename the file. The check said True, the open still fails, and your program crashes with FileNotFoundError anyway. The gap is called a race condition, or "time of check to time of use". It is rare on your own laptop and much less rare on a busy server where several processes share a folder.
The fix is to skip the separate check and let open() be the check. Python raises FileNotFoundError when the file is missing, and you handle that in except:
Output:
theme=dark
(no settings file, using defaults)
Now there is one operation instead of two, so there is nothing to race against. This style has a name in the Python community: EAFP, "easier to ask forgiveness than permission". The opposite style, checking first, is LBYL, "look before you leap". Python leans towards EAFP for file work because the operating system is the only thing that knows the answer at the moment you open the file.
FileNotFoundError is not the only thing that can go wrong. A path that is a directory raises IsADirectoryError (PermissionError on Windows), and a file you cannot read raises PermissionError. All three are subclasses of OSError, so except OSError: catches every "could not open it" case at once. The exceptions page covers how to choose between catching one specific error and catching a family.
When a Plain Check Is Fine
Checking first is not wrong in every case. It is the right tool when you only need the answer and are not about to act on the file in the next line:
- choosing which message to show ("Found 3 saved games")
- validating a path the user typed before starting a long job
- skipping work that was already done, where a stale answer only costs a repeat
The rule of thumb: if you are going to open, read, write or delete the file, do that inside try. If you only want to know, isfile() or Path.is_file() is fine.
Creating a File Only If It Does Not Exist
The reverse question comes up too: "write this file, but never overwrite an existing one". The obvious version has the same race as before:
if not os.path.exists("report.txt"):
with open("report.txt", "w") as f: # another process may create it first
f.write("new report\n")
Mode "x" (exclusive creation) does both steps in one. It creates the file, or raises FileExistsError if the name is taken:
Output:
attempt 1: created report.txt
attempt 2: report.txt already exists, left it alone
For folders, os.makedirs(path, exist_ok=True) and Path(path).mkdir(parents=True, exist_ok=True) create the directory and any missing parents, and do nothing if it is already there. There is no need to call isdir() first.
Common Mistakes
- Using
exists()when you mean a file. A directory with the same name passes the check. Useisfile()orPath.is_file(). - Forgetting where relative paths start.
"data.txt"is looked up in the current working directory, which is where you launched the program, not necessarily the folder that holds the script. To find a file next to the script, build the path fromPath(__file__).parent. - Checking, then opening. The file can change in between. Open inside
tryand handleFileNotFoundError. - Catching every exception.
except Exception:aroundopen()also hides typos and bugs in the code that reads the file. CatchFileNotFoundErrororOSError.
Frequently Asked Questions
How do I check if a file exists in Python?
Import os and call os.path.isfile("data.txt"), which returns True only for an existing regular file. With pathlib it is Path("data.txt").is_file(). Use os.path.exists() or Path.exists() when a directory with that name should count too.
What is the difference between os.path.exists and os.path.isfile?
os.path.exists(p) is True for anything at that path: a file, a directory, or a symlink that points somewhere real. os.path.isfile(p) is True only for a regular file, so it returns False for a directory. os.path.isdir(p) is the directory counterpart.
Should I check if a file exists before opening it?
Usually not. The file can be deleted or created between the check and the open() call, so the check does not guarantee anything. Open the file directly inside try and handle FileNotFoundError in except. A separate existence check is right when you only need the answer, for example to decide which message to show.
How do I create a file only if it does not exist?
Open it with mode "x": open("report.txt", "x"). Python creates the file, or raises FileExistsError if something is already there. The check and the creation happen in one step, so no other program can slip in between them.