Mateen Kiani
Published on Sun Jul 27 2025·3 min read
Creating a directory might sound trivial, but things can go sideways when the folder already exists. Many beginners end up with a FileExistsError
, while missing race conditions can trip up even seasoned developers. So, how can you ensure your Python script creates a directory only if it doesn’t exist, without raising errors or causing conflicts?
The good news is Python’s standard library has you covered. By combining os.makedirs
or pathlib.Path.mkdir
with simple checks and exception handling, you can write robust code that works safely in single-threaded and concurrent scenarios. Let’s dive in!
Before creating a directory, it’s tempting to just call mkdir()
and move on. But consider:
By explicitly handling the “exists” case, your script stays predictable. You can log meaningful messages, set permissions correctly, or even clean up old files.
Python’s os
module provides makedirs()
, which creates all intermediate-level directories needed to contain the leaf directory. To ignore FileExistsError
, pass exist_ok=True
in Python 3:
import ospath = 'data/output/logs'# Creates nested dirs, no error if already thereos.makedirs(path, exist_ok=True)
If you need custom error handling (e.g., permissions issues), wrap it in a try/except:
try:os.makedirs(path)print(f"Directory '{path}' created.")except FileExistsError:print(f"Directory '{path}' already exists.")except OSError as e:print(f"Failed to create directory: {e}")
Tip: Use
exist_ok=True
to simplify cases where you don’t need special logic on existing folders.
The pathlib
module offers an object-oriented approach:
from pathlib import Pathpath = Path('data/output/logs')# Creates dir, no error if existspath.mkdir(parents=True, exist_ok=True)
Pathlib makes chaining operations easier:
file_path = path / 'app.log'file_path.write_text('Log started')
In multi-threaded or multi-process code, a folder check followed by creation can still cause conflicts:
from pathlib import Pathpath = Path('shared/cache')# Danger: Might fail if created between check and mkdirif not path.exists():path.mkdir()
Better to rely on built-in flags:
try:path.mkdir(parents=True)except FileExistsError:pass # Safe: someone else created it
This pattern avoids a separate existence check and handles the edge case gracefully.
Sometimes you need custom permissions (e.g., 0o755
). Both os.makedirs
and pathlib.Path.mkdir
accept a mode
argument:
import osos.makedirs('scripts', mode=0o755, exist_ok=True)# Or with pathlibfrom pathlib import PathPath('scripts').mkdir(mode=0o755, exist_ok=True)
Make sure your umask doesn’t mask out intended bits. If necessary, adjust it at runtime:
old_umask = os.umask(0)os.makedirs('reports', mode=0o777, exist_ok=True)os.umask(old_umask)
Once your directory exists, you often create or move files into it. For moving, check out how to move files in Python. To inspect content, the guide on listing directory contents in Python is handy.
Example:
import shutiltarget = Path('cache/data.csv')if not target.exists():# generate datawith open(target, 'w') as f:f.write('id,value\n1,100')# Move to archivearchive_dir = Path('archive')archive_dir.mkdir(exist_ok=True)shutil.move(str(target), str(archive_dir / target.name))
Safely creating directories in Python is straightforward when you leverage exist_ok=True
and proper exception handling. Use os.makedirs
for procedural code or pathlib.Path.mkdir
for a more readable approach. Always handle race conditions and set permissions explicitly to avoid surprises. With these patterns in your toolkit, your file and folder operations will be robust and maintainable.