Python Check if File Exists

Learn how to check if a file exists in Python using pathlib Path.exists(), Path.is_file(), os.path.exists(), and os.path.isfile(), with examples for directories, symlinks, and file errors.

Published

Updated

Read time 7 min read

Reviewed byDeepak Prasad

Python Check if File Exists

Checking paths before reading or writing is a routine part of file I/O. For new code, the pathlib module is usually the clearest choice: it treats paths as objects and pairs well with open() and other APIs. The older os.path functions remain common in existing projects—build string paths with os.path.join instead of concatenating slashes by hand. This page orders ideas as pathlib first, then os.path, then file vs directory, and finally opening with try / except so existence checks line up with how the interpreter and OS actually behave. For writing after a check, see Python write to file.

Tested on: Python 3.13.3; kernel 6.14.0-37-generic.


Check if a file exists using pathlib

The documentation describes pathlib as providing object-oriented filesystem paths. A Path wraps a string path and exposes exists(), is_file(), is_dir(), and related checks without splitting string logic across the codebase.

When the question is specifically “is there a regular file here?”, Path.is_file() is the direct test (it follows symlinks to the target; a symlink pointing at a file counts as a file).

python
from pathlib import Path

path = Path("data.txt")
if path.is_file():
    print("File exists")
else:
    print("File does not exist")
Output

If data.txt is missing or the path is a directory, is_file() is False. The snippet assumes the process current working directory contains data.txt; relative paths depend on where the script is launched from.


Check if a path exists using Path.exists()

Path.exists() returns True if anything exists at that path that stat() can resolve: a regular file, a directory, or a symlink whose target is reachable. It is False for a missing path and typically False for a broken symlink (nothing to stat at the leaf).

python
import tempfile
from pathlib import Path

with tempfile.TemporaryDirectory() as d:
    base = Path(d)
    (base / "any.txt").write_text("x", encoding="utf-8")
    (base / "folder").mkdir()
    print((base / "any.txt").exists())   # True: file
    print((base / "folder").exists())    # True: directory
    print((base / "missing").exists())   # False
Output

Use exists() when the program only needs to know “is there something at this path?” before choosing the next step (for example, creating a parent folder vs opening a file).


Check if the path is a file using Path.is_file()

Path.is_file() is True only when the path refers to an existing regular file (or a symlink whose final target is a regular file). A directory or a broken symlink yields False.

python
import tempfile
from pathlib import Path

with tempfile.TemporaryDirectory() as d:
    base = Path(d)
    f = base / "demo.txt"
    f.write_text("hello", encoding="utf-8")
    (base / "subdir").mkdir()
    print(f.is_file())              # True
    print((base / "subdir").is_file())  # False: it is a directory
Output

Check if a file exists using os.path.exists()

os.path.exists(path) mirrors Path.exists(): True for an existing file, directory, or working symlink. It does not distinguish object types.

python
import os
import os.path
import tempfile

with tempfile.NamedTemporaryFile(delete=False) as tmp:
    name = tmp.name
try:
    print(os.path.exists(name))  # True while the file is present
finally:
    os.unlink(name)
    print(os.path.exists(name))  # False after removal
Output

Check if a file exists using os.path.isfile()

os.path.isfile(path) is True only for an existing regular file (symlinks to files count). Directories return False.

python
import os
import os.path
import tempfile

with tempfile.NamedTemporaryFile(delete=False) as tmp:
    name = tmp.name
print(os.path.isfile(name))  # True
os.unlink(name)
print(os.path.isfile(name))  # False
Output

exists() vs is_file() (pathlib and os.path)

Question pathlib os.path
Does anything exist here (file, directory, or a symlink whose target stat succeeds)? Path(p).exists() os.path.exists(p)
Is this path a regular file (or a symlink whose final target is a regular file)? Path(p).is_file() os.path.isfile(p)

Use is_file() / isfile() before reading file bytes so a directory at the same path does not pass the check. Use exists() when the logic only needs “nothing vs something” (for example skipping mkdir when the path is already taken). Mixing the two often shows up as bugs where a directory name is passed into APIs that expect a file path.


Check if a file exists before reading

An explicit check keeps error messages and control flow in application code instead of the default FileNotFoundError traceback—useful for CLI messages or skipping optional inputs.

python
from pathlib import Path

path = Path("config.json")
if not path.is_file():
    raise SystemExit("config.json is required next to this script")
text = path.read_text(encoding="utf-8")
Output

Remember the time gap between the check and read_text: another process can remove the file in between, so the read can still fail.


Better option: handle FileNotFoundError while opening

Opening (or using Path.read_text) inside try / except FileNotFoundError handles both “never existed” and “disappeared after a check” without a race between two OS calls. That pattern is the usual recommendation for robust readers. For causes, errno 2 text, and path debugging, see FileNotFoundError in Python.

python
try:
    with open("data.txt", "r", encoding="utf-8") as file:
        content = file.read()
except FileNotFoundError:
    print("File does not exist")
Output

The same idea applies to Path.read_text() and to catching OSError when both missing files and permission errors must be grouped.


Check if a directory exists

Directories satisfy exists() but not is_file(). Use Path.is_dir() or os.path.isdir() when the path must be a folder (for example before mkdir parents or walking logs).

python
from pathlib import Path
import tempfile

with tempfile.TemporaryDirectory() as d:
    path = Path(d)
    print(path.is_dir())    # True
    print(path.is_file())   # False
Output

Path.is_symlink() and os.path.islink() test whether the path itself is a symlink entry, without requiring the target to exist. A broken link can still be is_symlink() True while exists() is False. For day-to-day “is this a normal file I can open?”, prefer is_file(); reserve symlink-specific checks for packaging, deployment, or security reviews. Linux background on creating links: create symbolic link.

python
import os
import tempfile
from pathlib import Path

with tempfile.TemporaryDirectory() as d:
    base = Path(d)
    target = base / "target.txt"
    target.write_text("x", encoding="utf-8")
    link = base / "link.txt"
    link.symlink_to(target)
    print(link.is_symlink(), link.is_file())  # True True: link points to a file
    target.unlink()
    print(link.is_symlink(), link.exists(), link.is_file())  # e.g. True False False after target removed (Linux)
Output

On Linux, deleting the target file usually leaves the symlink entry in place: is_symlink() stays true while exists() and is_file() become false until the link itself is deleted. Other platforms can differ slightly; treat “symlink present” and “open will succeed” as separate checks.


Common mistakes when checking file existence

  • Using exists() (or os.path.exists()) when the code must only accept a regular file; a directory at the same path still makes exists() true.
  • Assuming a relative path is relative to the script file—it is relative to the current working directory, which differs in IDEs, cron, and systemd units compared to an interactive shell.
  • Relying on “check then open” without handling FileNotFoundError, so a race or stale check still crashes the program.
  • Treating a broken symlink as “file exists” because older logic only called islink(); combine is_file() or exists() with the behavior the read API needs.
  • Case sensitivity on Linux: Path("Data.txt") and Path("data.txt") are different paths; on typical Windows volumes the same spelling may collide depending on filesystem rules.

Python file exists quick reference table

Need Use
Path is a regular file Path("file.txt").is_file()
Path exists as file, directory, or resolvable link Path("file.txt").exists()
Classic API: regular file os.path.isfile(path)
Classic API: any existing path os.path.exists(path)
Directory Path("folder").is_dir()
Safer read try / except FileNotFoundError around open or read_text
Symlink entry (path is a link) Path(path).is_symlink() or os.path.islink(path)

Summary

Prefer pathlib.Path for new Python: use is_file() when only a regular file counts, and exists() when any present path is enough. On legacy code, os.path.isfile and os.path.exists follow the same split. Directories are handled with is_dir() or os.path.isdir. Because the filesystem can change between a check and an open, pairing checks with try / except FileNotFoundError (or reading directly and catching the error) is more reliable than a bare check alone; see try / except in Python for broader patterns.


References


Frequently Asked Questions

1. Should I use Path.exists() or Path.is_file() in Python?

Use Path.is_file() when the path must be a regular file; use Path.exists() when any filesystem object at that path is enough, including directories or symlinks that resolve.

2. What is the race condition when checking if a file exists before opening?

Another process can delete or replace the file after exists() or is_file() returns True but before open() runs; handling FileNotFoundError on open is safer than relying on the check alone.

3. Does os.path.exists() return True for a directory?

Yes—os.path.exists() is True for any existing path that stat can resolve, including directories; use os.path.isfile() or Path.is_file() when only a regular file should count.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …