Free tools Windows power users keep installed
One-click scans. No signup required.
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
For new Python code, use pathlib.Path: Path.exists() checks for any existing filesystem entry, while Path.is_file() and Path.is_dir() require a specific type. The older os.path functions answer the same questions when your code already uses strings. If you are about to read, copy, or delete something, attempting that operation and handling its exception can be safer than performing a separate pre-check.
1. Check for any existing entry with Path.exists()
Use exists() when either a file or a directory is acceptable:
from pathlib import Path
path = Path("config.json")
if path.exists():
print("The path exists")
else:
print("Nothing exists at that path")
Path.exists() returns True when the path points to an existing file or directory. It normally follows symbolic links, so a link to an existing target is reported as existing. A missing path and a broken link return False.
2. Require a regular file with Path.is_file()
Use is_file() when a directory must not satisfy the test:
#1 Best Overall
from pathlib import Path
if Path("config.json").is_file():
print("config.json is a regular file")
else:
print("It is missing or is not a regular file")
This predicate is false for directories, missing paths, and broken symbolic links. It normally follows a symbolic link to a regular file. The test says what the path is now; it does not guarantee that the file will remain available for a later operation.
3. Require a directory with Path.is_dir()
Use is_dir() when you need a folder:
from pathlib import Path
folder = Path("data")
if folder.is_dir():
print("data is a directory")
else:
print("data is missing or is not a directory")
Files and missing paths return False. Like the other pathlib predicates, this test follows symbolic links by default. A successful directory test does not prove that your process has permission to list or modify the directory.
4. Check a path string with os.path.exists()
os.path is the traditional, string-oriented interface. It also accepts path-like objects and is useful when passing paths to older APIs:
import os
if os.path.exists("config.json"):
print("The path exists")
Use this when the question is “does any file or directory exist here?” For new code, converting the value to a Path often makes later joins and operations clearer, but there is no need to rewrite stable legacy code solely to change the spelling.
5. Test for a regular file with os.path.isfile()
import os
if os.path.isfile("config.json"):
print("It is a regular file")
else:
print("It is not a usable regular file")
os.path.isfile() returns true for an existing regular file and follows symbolic links. It returns false for directories, missing paths, and broken links.
Rank #2
6. Test for a directory with os.path.isdir()
import os
if os.path.isdir("data"):
print("data is a directory")
else:
print("data is not an existing directory")
This is the direct os.path equivalent of Path.is_dir(). It is convenient when the rest of an application already stores paths as strings or calls other os.path functions.
7. Discover a match or perform the real operation
Find matching children with glob()
If the real question is whether a directory contains a matching child, test the results of a pattern rather than the directory itself:
from pathlib import Path
csv_files = Path("data").glob("*.csv")
if any(csv_files):
print("At least one CSV file exists")
else:
print("No CSV files were found")
glob() and rglob() yield matching paths. Their results are not guaranteed to be ordered. Recursive patterns such as ** can scan a large tree, so constrain the starting directory and pattern when performance matters.
Inspect children with iterdir()
from pathlib import Path
folder = Path("data")
try:
for child in folder.iterdir():
print(child)
except NotADirectoryError:
print("data is not a directory")
except OSError as exc:
print(f"Could not read data: {exc}")
iterdir() yields direct children. It raises OSError when the parent is inaccessible or is not a directory, so do not replace this operation with a bare existence check.
Attempt the operation and handle absence
A separate check can become stale between the check and the operation: another process may remove or replace the path. When reading is the goal, combine the attempt with the error handling:
from pathlib import Path
try:
text = Path("config.json").read_text(encoding="utf-8")
except FileNotFoundError:
text = ""
except OSError as exc:
print(f"The file could not be read: {exc}")
raise
FileNotFoundError specifically describes a required path that is absent. Other OSError subclasses can indicate permissions, a device problem, or another filesystem failure. Catch only the failures you can handle.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsWhich method should you choose?
| Question | Recommended API | What it distinguishes |
|---|---|---|
| Does anything exist at this path? | Path.exists() or os.path.exists() |
File, directory, or another existing entry versus missing |
| Is this a regular file? | Path.is_file() or os.path.isfile() |
Regular file versus directory or missing path |
| Is this a directory? | Path.is_dir() or os.path.isdir() |
Directory versus file or missing path |
| Does a child matching a pattern exist? | glob(), rglob(), or iteration |
Discovery of matching children |
| Will a read, write, copy, or delete work? | Attempt the operation and catch its documented exception | The operation’s actual result, including permission and I/O failures |
Prefer pathlib for new code because one Path object supports checking, joining, opening, and other filesystem operations. Prefer os.path when an existing interface expects strings or your project consistently uses that API. Neither family is universally faster; choose based on the question and the surrounding code.
Symbolic links, inaccessible paths, and Python versions
- These predicates normally follow symbolic links and report on the target. A link to a regular file therefore satisfies
is_file(); a broken link does not. - In newer pathlib versions,
Path.exists(follow_symlinks=False)can test the link entry itself rather than following it. Use that form when link identity matters, and verify the Python version running your program supports the parameter. - Since Python 3.8, pathlib and
os.pathpredicates returnFalseinstead of raising for paths containing characters that cannot be represented by the operating system. - A false predicate is not proof that a path is safe to use. Permissions, race conditions, mount failures, and other I/O errors can still affect the operation. Directory iteration and file operations may raise
OSErroror a more specific exception.
Common mistakes and fixes
Using exists() when a directory is required
A file named data makes Path("data").exists() true. Use is_dir() before treating it as a folder.
Opening a path after a check without handling races
Another process can remove the file after exists() returns. Prefer a try/except FileNotFoundError around the open or read when the operation is the real objective.
Assuming a false result means “permission denied”
Predicates can return false for missing, broken-link, or unrepresentable paths. If you need to diagnose access, perform the operation and inspect the resulting OSError.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchScanning an entire tree unnecessarily
rglob() with a broad recursive pattern can traverse a very large directory. Narrow the root and pattern, or stop after the first match with next():
from pathlib import Path
match = next(Path("data").glob("*.csv"), None)
if match is not None:
print(match)
Confusing a path relative to the current directory
Relative paths are resolved from the process’s current working directory, which may differ from the script’s directory. Print Path.cwd() while diagnosing an unexpected result, and construct an explicit base path when your application requires one.
Or skip the browser setup
If your Python workflow also needs website screenshots, ScreenshotNeo provides a one-call API rather than a locally managed browser. It removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, failed loads, and cache hits are not billed. Its MCP server lets AI agents such as Claude or Cursor call screenshot tools directly. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000 shots.
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
See the ScreenshotNeo API documentation for options such as PNG, JPEG, PDF, full-page capture, selectors, custom JavaScript, waits, headers, cookies, and signed links. Create a free ScreenshotNeo account to get the 1,000 monthly screenshots without a card.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →FAQ
Does Path.exists() check only files?
No. It reports an existing file or directory. Use is_file() or is_dir() when type matters.
Should I use pathlib or os.path?
Use pathlib for new code and os.path when compatibility with string-based code or a legacy interface is the priority.
Best Value
How can I check whether a folder contains at least one CSV?
Use any(Path(folder).glob("*.csv")), or retrieve the first result with next(..., None) when you do not need every match.
Can a check guarantee that a subsequent open will succeed?
No. The filesystem can change between two statements, and permissions or I/O faults can still prevent the operation. Handle the operation’s exception.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Frequently Asked Questions
Does Path.exists() check only files?
No. It reports an existing file or directory. Use is_file() or is_dir() when type matters.
Should I use pathlib or os.path?
Use pathlib for new code and os.path when compatibility with string-based code or a legacy interface is the priority.
How can I check whether a folder contains at least one CSV?
Use any(Path(folder).glob("*.csv")), or retrieve the first result with next(..., None) when you do not need every match.
Can a check guarantee that a subsequent open will succeed?
No. The filesystem can change between two statements, and permissions or I/O faults can still prevent the operation. Handle the operation’s exception.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

