os.makedirs

os.makedirs(path, exist_ok=True) is 'mkdir -p': it creates every missing level and is happy if the folder already exists. os.mkdir creates exactly one level and fails if the parent is missing or the name is taken. To delete, rmdir removes one empty folder and removedirs also prunes the parents that become empty.

os functionPython 3.0+ (exist_ok 3.2+)Live demo
Common call
os.makedirs('build/reports', exist_ok=True)
Returns
None
Replaces
if not os.path.exists(p): os.mkdir(p) — and recursive mkdir code
Watch out
exist_ok=True still raises if the name exists as a file
os.makedirs(namename — The folder to create (makedirs: with all its parents).type: str | PathLike · required, modemode — Permission bits, reduced by the umask. Since 3.7 makedirs applies it only to the last folder; parents get the default.type: int · default: 0o777=0o777, exist_okexist_ok — makedirs only: True means "no error if the folder already exists" — but a file of that name still raises FileExistsError.type: bool · default: False=False) / os.mkdir(path, modemode — Permission bits, reduced by the umask. Since 3.7 makedirs applies it only to the last folder; parents get the default.type: int · default: 0o777=0o777, *, dir_fd=None) / os.rmdir(path) / os.removedirs(name)
→ None

Demo

Live evaluation
Create some folders first, then try os.mkdir on one path.
Try:
Inputs
existinglist[str]folders that already exist
pathstrfolder to create
Code
import os
for d in ['logs']:
    os.makedirs(d)
try:
    os.mkdir('logs/2026')
    result = 'created'
except OSError as e:
    result = type(e).__name__
result
Result
'created'

mkdir fails with FileExistsError when the name is taken and FileNotFoundError when a parent is missing — makedirs creates the parents. Without exist_ok, makedirs also raises FileExistsError for an existing folder; with exist_ok=True the second call is silent. removedirs deletes a/b/c, then tries b, then a, and stops quietly at the first folder that is not empty (a still holds keep.txt). The class names are the same on every OS; the error messages differ ("[Errno 17] File exists" on Linux, "[WinError 183] …" on Windows).

Parameters

NameTypeRequiredDescription
namestr | PathLikeyesThe folder to create (makedirs: with all its parents).
modeintno (0o777)Permission bits, reduced by the umask. Since 3.7 makedirs applies it only to the last folder; parents get the default.
exist_okboolno (False)makedirs only: True means "no error if the folder already exists" — but a file of that name still raises FileExistsError.

Return value

None — All four change the file system and return None, or raise an OSError subclass.

Common patterns

Ensure an output folder
Idempotent, no race between check and create.
import os
os.makedirs(os.path.join('out', 'reports'), exist_ok=True)
Ensure the folder for a file
dirname is '' for a bare file name — guard it.
import os
folder = os.path.dirname(target)
if folder:
    os.makedirs(folder, exist_ok=True)
Create only if new (claim a name)
mkdir is atomic: exactly one process wins.
import os
try:
    os.mkdir('lockdir')
except FileExistsError:
    print('someone else is running')
Remove a folder with contents
rmdir and removedirs refuse non-empty folders; shutil does the whole tree.
import shutil
shutil.rmtree('build', ignore_errors=True)

Examples

1. makedirs creates the whole chain
import os os.makedirs('a/b/c') os.path.isdir('a/b/c')
Returns
True
2. exist_ok=True: a second call is fine
import os os.makedirs('logs', exist_ok=True) os.makedirs('logs', exist_ok=True) os.listdir('.')
Returns
['logs']
3. mkdir needs the parent
import os try: os.mkdir('x/y') except OSError as e: result = type(e).__name__ result
Returns
'FileNotFoundError'
4. Existing folder without exist_ok
import os os.mkdir('data') try: os.makedirs('data') except FileExistsError as e: result = (type(e).__name__, e.errno) result
Returns
('FileExistsError', 17)
5. rmdir only removes empty folders
import os os.makedirs('d/sub') try: os.rmdir('d') except OSError as e: result = type(e).__name__ result
Returns
'OSError'
6. removedirs prunes empty parents
import os os.makedirs('a/b/c') os.removedirs('a/b/c') os.listdir('.')
Returns
[]
7. A trailing slash is fine
import os os.makedirs('out/reports/', exist_ok=True) os.path.isdir('out/reports')
Returns
True

Pitfalls

1. exist_ok does not cover a file with that name
exist_ok only forgives an existing folder. If a file has the name, makedirs still raises FileExistsError.
name taken by a file
import os
open('output', 'w').close()
try:
    os.makedirs('output', exist_ok=True)
except OSError as e:
    result = type(e).__name__
result
'FileExistsError'
check what is there
import os
open('output', 'w').close()
if os.path.isfile('output'):
    os.replace('output', 'output.old')
os.makedirs('output', exist_ok=True)
os.path.isdir('output')
True
2. Using mkdir for nested folders
mkdir creates one level only.
mkdir('a/b/c')
import os
try:
    os.mkdir('a/b/c')
except OSError as e:
    result = type(e).__name__
result
'FileNotFoundError'
makedirs('a/b/c')
import os
os.makedirs('a/b/c')
os.path.isdir('a/b/c')
True
3. Calling makedirs on a bare file name's folder
os.path.dirname('report.txt') is '', and makedirs('') raises FileNotFoundError. Use 'or "."' or skip the call.
makedirs('')
import os
try:
    os.makedirs(os.path.dirname('report.txt'), exist_ok=True)
except OSError as e:
    result = type(e).__name__
result
'FileNotFoundError'
or '.'
import os
os.makedirs(os.path.dirname('report.txt') or '.', exist_ok=True)
os.path.isdir('.')
True

When to use

Use it
  • Making sure a folder exists before writing into it (makedirs, exist_ok=True)
  • Atomically claiming a name (mkdir raises if it exists)
  • Removing empty folders (rmdir, removedirs)
Reach for something else
  • Deleting non-empty folders → shutil.rmtree
  • Temporary folders → tempfile.TemporaryDirectory / mkdtemp
  • Object paths → Path.mkdir(parents=True, exist_ok=True)

Notes

CPython impl
mkdir and rmdir are C calls (Modules/posixmodule.c); makedirs and removedirs are short pure-Python functions in Lib/os.py built on split, exists, mkdir and rmdir
mode
Ignored on Windows, apart from mode 0o700, which since 3.13 limits access to the current user and administrators. On POSIX the umask is masked out first
exist_ok
Added in 3.2; since 3.4.1 makedirs no longer raises when mode differs from the existing folder
removedirs
Errors while pruning parents are ignored — they simply mean the parent was not empty

FAQ

os.makedirs(path, exist_ok=True). It creates any missing parents too, and it avoids the race of checking os.path.exists first.