os.path.exists

exists is True for anything — file, folder, device; isfile only for regular files; isdir only for folders. They follow symlinks: a link to a missing target is not "existing", but lexists and islink still see the link itself. A checked answer can be stale a moment later; for creating or opening, just try and catch the error.

os.path functionPython 3.0+Live demo
Common call
if os.path.isfile(path):
Returns
bool
Replaces
try: os.stat(path) except OSError: …
Watch out
exists() is True for folders too — use isfile() before reading
os.path.exists(path) / isfile(path) / isdir(path) / islink(path) / lexists(path)
→ bool

Demo

Live evaluation
Create some files (folders appear on the way), then check several paths.
Try:
Inputs
fileslist[str]files to create, comma-separated
checkslist[str]paths to check, comma-separated
Code
import os
for f in ['README.md', 'src/app.py']:
    os.makedirs(os.path.dirname(f) or '.', exist_ok=True)
    open(f, 'w').close()
[(p, os.path.exists(p), os.path.isfile(p), os.path.isdir(p)) for p in ['README.md', 'src', 'src/main.py']]
Result
[('README.md', True, True, False), ('src', True, False, True), ('src/main.py', False, False, False)]

A missing path is (False, False, False) — no exception. A folder exists but is not a file. '.' and 'a/..' are folders too (os.path does not normalize, the OS resolves '..'). The empty string is never an existing path. None of the created files is a symlink, so islink would be False for all of them and lexists would equal exists.

Parameters

NameTypeRequiredDescription
pathstr | bytes | PathLike | intyesThe path to check. exists also accepts an open file descriptor (3.3+).

Return value

bool — True or False. Errors (missing path, permission problems, invalid names) give False.

Common patterns

Read a file if present
Fine when nothing else touches the file meanwhile.
import os
text = open(path, encoding='utf-8').read() if os.path.isfile(path) else ''
EAFP: try and handle the error
No race between check and use.
try:
    with open(path, encoding='utf-8') as f:
        text = f.read()
except FileNotFoundError:
    text = ''
Find a broken symlink
The link is there (lexists) but its target is not (exists).
import os
broken = os.path.lexists(p) and not os.path.exists(p)
First existing candidate
A common lookup for config files.
import os
candidates = ['./app.toml', os.path.expanduser('~/.config/app.toml'), '/etc/app.toml']
config = next((c for c in candidates if os.path.isfile(c)), None)

Examples

1. File, folder, missing
import os os.makedirs('src') open('src/app.py', 'w').close() [(p, os.path.exists(p), os.path.isfile(p), os.path.isdir(p)) for p in ['src', 'src/app.py', 'src/x.py']]
Returns
[('src', True, False, True), ('src/app.py', True, True, False), ('src/x.py', False, False, False)]
2. A regular file is not a link
import os open('a.txt', 'w').close() (os.path.islink('a.txt'), os.path.lexists('a.txt'))
Returns
(False, True)
3. The empty string
import os os.path.exists('')
Returns
False
4. Invalid names: False, not an error
import os os.path.exists('bad\0name')
Returns
False
5. An open file descriptor
import os with open('f.txt', 'w') as fh: fd_ok = os.path.exists(fh.fileno()) fd_ok
Returns
True
6. The current folder
import os os.path.isdir('.')
Returns
True

Pitfalls

1. Using exists() before reading a file
A folder of that name passes exists() and then open() fails.
exists()
import os
os.mkdir('data.csv')
os.path.exists('data.csv')
True
isfile()
import os
os.mkdir('data.csv')
os.path.isfile('data.csv')
False
2. Check-then-create
Another process can create the folder between the check and mkdir. Let makedirs handle it.
exists() + mkdir()
import os
if not os.path.exists('out'):
    os.mkdir('out')
os.path.isdir('out')
True
makedirs(exist_ok=True)
import os
os.makedirs('out', exist_ok=True)
os.path.isdir('out')
True

When to use

Use it
  • Branching on what kind of thing a path is
  • Filtering listdir results (join the name with the folder first)
Reach for something else
  • Guarding open/create/delete → just do it and catch FileNotFoundError / FileExistsError
  • pathlib code → Path.exists() / is_file() / is_dir() / is_symlink()
  • Size or time → getsize / getmtime / os.stat

Notes

CPython impl
genericpath.exists, isfile and isdir call os.stat and test st_mode; islink and lexists use os.lstat. On Windows, faster C versions in nt are used for some of them
Errors
Any OSError or ValueError (e.g. an embedded NUL character) becomes False — including permission errors, so False does not always mean "missing"
Symlinks
exists, isfile and isdir follow links; islink and lexists look at the link itself

FAQ

os.path.isfile(path) — True only for an existing regular file. os.path.exists(path) is also True for folders. With pathlib: Path(path).is_file().