Check If a File Exists and Create It If Not in Python

The safest way to check if a file exists and create it if not in Python is one call: open it in "x" mode inside a try block. Python creates a missing file and raises FileExistsError for an existing one, so old data stays safe:

try:
    with open("report.txt", "x", encoding="utf-8") as f:
        f.write("first line\n")
except FileExistsError:
    pass  # the file was already there

Every run you see below was done on Python 3.12.5 on Windows 11, and the output blocks are copied from those runs.

In this tutorial, I’ll show the classic exists-then-create check, the x mode, Path.touch(), append mode for logs, and how to create missing folders along the way.

Check if a file exists with os.path, then create it

The most readable version asks first and creates second. I ran the same check twice so you can see both branches:

import os
from pathlib import Path

Path("customers.txt").unlink(missing_ok=True)      # start clean for the demo

for run in (1, 2):
    if not os.path.exists("customers.txt"):
        with open("customers.txt", "w", encoding="utf-8") as f:
            f.write("Emily Carter,Austin TX\n")
        print(f"run {run}: customers.txt was missing, created it")
    else:
        print(f"run {run}: customers.txt already exists, left it alone")

print("isfile:", os.path.isfile("customers.txt"), "| exists:", os.path.exists("customers.txt"))
Path("archive").mkdir(exist_ok=True)
print("folder 'archive' -> exists:", os.path.exists("archive"), "| isfile:", os.path.isfile("archive"))

Output:

run 1: customers.txt was missing, created it
run 2: customers.txt already exists, left it alone
isfile: True | exists: True
folder 'archive' -> exists: True | isfile: False
Command Prompt output of a Python script that checks if customers.txt exists with os.path.exists and creates it only on the first run
The first pass creates customers.txt; the second finds it and leaves it alone. A folder passes exists() but fails isfile().

Notice the last line. os.path.exists() is True for folders too, so os.path.isfile() is the safer test when you really mean a file.

Every way to test for a file, including Path.is_file(), is in checking if a file exists in Python.

This pattern has one weak spot. Between the check and the open() call, another process could create the same file, and "w" would then wipe it. That gap is called a race condition.

Create the file only if it doesn’t exist with x mode

Mode "x" does the check and the create in one step, so there’s no gap. Here I try to create the same invoice twice:

from pathlib import Path

Path("invoice_1001.txt").unlink(missing_ok=True)   # start clean for the demo

def create_once(name, text):
    try:
        with open(name, "x", encoding="utf-8") as f:   # x = create, fail if it exists
            f.write(text)
        return "created"
    except FileExistsError:
        return "skipped, already there"

print(create_once("invoice_1001.txt", "Invoice 1001 for $249.99, due 2026-11-15\n"))
print(create_once("invoice_1001.txt", "Invoice 1001 for $0.00\n"))
print("file holds:", Path("invoice_1001.txt").read_text(encoding="utf-8").strip())

Output:

created
skipped, already there
file holds: Invoice 1001 for $249.99, due 2026-11-15
Command Prompt output of Python open() in x mode creating invoice_1001.txt once and skipping it with FileExistsError the second time
The second call hits FileExistsError, so the original invoice text survives.

The second call didn’t overwrite the $249.99 invoice with $0.00. That’s exactly what you want for receipts, exports and anything else you can’t afford to lose.

I reach for x whenever a script might run twice. The other ways to make files are in creating a new file in Python, and every mode is explained in opening a file in Python.

Create an empty file with pathlib touch()

Path.touch() works like the Linux touch command. With exist_ok=True it creates a missing file and quietly accepts an existing one:

from pathlib import Path

notes = Path("notes.txt")
notes.unlink(missing_ok=True)                       # start clean for the demo

notes.touch(exist_ok=True)                          # missing -> creates an empty file
print("after 1st touch:", notes.exists(), notes.stat().st_size, "bytes")

notes.write_text("Call Denver office on 2026-11-02\n", encoding="utf-8")
notes.touch(exist_ok=True)                          # exists -> content stays
print("after 2nd touch:", notes.stat().st_size, "bytes ->", notes.read_text(encoding="utf-8").strip())

try:
    notes.touch(exist_ok=False)
except FileExistsError as err:
    print("exist_ok=False ->", type(err).__name__)

Output:

after 1st touch: True 0 bytes
after 2nd touch: 34 bytes -> Call Denver office on 2026-11-02
exist_ok=False -> FileExistsError
Command Prompt output of Python pathlib Path.touch with exist_ok True creating notes.txt and keeping its content on a second touch
The first touch() makes an empty file, the second keeps the saved note, and exist_ok=False raises FileExistsError.

Touching an existing file doesn’t clear it. It only updates the modified time, which is why the note about the Denver office is still there afterwards.

Use touch() when you just need the file to exist, such as a marker or lock file. When you also need to write a first line, x mode is cleaner.

Create or append to a file with a mode

For logs you usually want “create it the first time, add to it after that”. Mode "a" does both, and checking first tells you when to write a header:

from pathlib import Path

log = Path("sales_log.csv")
log.unlink(missing_ok=True)                         # start clean for the demo

def add_sale(date, city, amount):
    new_file = not log.exists()
    with open(log, "a", encoding="utf-8") as f:     # a = create if missing, else add to the end
        if new_file:
            f.write("date,city,amount\n")
        f.write(f"{date},{city},{amount:.2f}\n")

add_sale("2026-10-26", "Austin", 49.99)
add_sale("2026-10-27", "Seattle", 120.50)
print(log.read_text(encoding="utf-8").strip())

Output:

date,city,amount
2026-10-26,Austin,49.99
2026-10-27,Seattle,120.50

The header appears once even though add_sale() ran twice. Mode "a" never deletes anything, so you can call it from a scheduled job every day.

Mode "w" is the opposite: it empties the file before writing. When that’s what you want, see overwriting a file in Python.

Create the missing folders before the file

None of these methods create folders. If the parent folder isn’t there, open() raises FileNotFoundError, so make the folders first:

from pathlib import Path
import shutil

shutil.rmtree("reports", ignore_errors=True)        # start clean for the demo
target = Path("reports") / "2026" / "october.txt"

try:
    with open(target, "x", encoding="utf-8") as f:
        f.write("October total: $18,420.00\n")
except FileNotFoundError as err:
    print("no folder yet ->", type(err).__name__)

target.parent.mkdir(parents=True, exist_ok=True)    # make reports\2026 first
with open(target, "x", encoding="utf-8") as f:
    f.write("October total: $18,420.00\n")
print("created:", target, "->", target.exists())

Output:

no folder yet -> FileNotFoundError
created: reports\2026\october.txt -> True
Command Prompt output of Python failing to create reports/2026/october.txt until Path.mkdir with parents=True makes the folders
The first attempt fails because reports\2026 is missing; after mkdir(parents=True, exist_ok=True) the file is created.

parents=True builds the whole chain, and exist_ok=True stops an error when the folders already exist. More options are in creating a directory in Python.

If the script must find files next to itself, build the path from __file__, as shown in getting the path of the current file in Python.

Which method should you use to create a file if it’s missing?

All five work. Pick the one that matches what should happen when the file is already there:

MethodIf the file existsBest for
os.path.exists() + "w"Skipped by your ifSimple scripts, one process
open(path, "x")Raises FileExistsErrorNever overwriting data
Path.touch(exist_ok=True)Kept, time updatedEmpty marker files
open(path, "a")New text goes at the endLogs and CSV rows
mkdir(parents=True) first–Paths with new folders

My default is x mode for new files and a mode for logs. When you also need to report a missing file to the user, see handling a file that does not exist in Python.

These guides pick up once your file exists:

Frequently asked questions

How do I create a file in Python only if it doesn’t exist?

Open it with open(path, "x") inside try and catch FileExistsError. The file is created only when it’s missing.

Does open() with w mode create a file if it doesn’t exist?

Yes, but it also empties the file if it already exists. Use "a" or "x" when the old content must stay.

Does Path.touch() overwrite an existing file?

No. With exist_ok=True it keeps the content and only updates the modified time.

Should I use os.path.exists() or os.path.isfile()?

Use isfile() when you need a regular file; exists() is also True for folders.

Why do I get FileNotFoundError when creating a file?