Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
os.mkdir() creates exactly one directory. It succeeds only when the target name is unused and its parent already exists:
import os
os.mkdir("reports")
The function returns None. It does not create missing parent directories, create files, or accept an exist_ok argument. For nested paths or idempotent setup, use os.makedirs() or pathlib.Path.mkdir().
Syntax and core behavior
os.mkdir(path, mode=0o777, *, dir_fd=None)
The path can be a string, bytes, or a path-like object such as pathlib.Path (supported since Python 3.6). mode requests initial permission bits where the operating system supports them. dir_fd is an optional directory-descriptor-relative form for advanced code.
See the Python documentation for os.mkdir().
Create one directory
import os
os.mkdir("data")
If the call succeeds, a directory named data appears in the process’s current working directory. Check that location with:
#1 Best Overall
import os
print(os.getcwd())
A relative path is relative to the current working directory, not automatically to the directory containing your Python file.
Relative and absolute paths
Relative paths
import os
print(os.getcwd())
os.mkdir("logs")
Launchers, IDEs, test runners, and services can choose different working directories. If the directory must sit beside the script, construct the path explicitly:
from pathlib import Path
project_root = Path(__file__).resolve().parent
logs_dir = project_root / "logs"
logs_dir.mkdir()
Absolute paths
import os
os.mkdir("/tmp/my_app_logs")
On Windows, avoid unescaped backslashes. Use a raw string, doubled backslashes, or a Path:
import os
from pathlib import Path
os.mkdir(r"C:UsersAliceDocumentslogs")
os.mkdir("C:\Users\Alice\Documents\logs")
Path(r"C:UsersAliceDocumentslogs").mkdir()
Existing targets and race-safe handling
If the target already names a directory, the default behavior is an exception:
import os
os.mkdir("logs")
os.mkdir("logs") # FileExistsError
os.mkdir() has no exist_ok parameter. When an existing directory is acceptable, handle the exception and verify the object is actually a directory:
Rank #2
import os
try:
os.mkdir("logs")
except FileExistsError:
if not os.path.isdir("logs"):
raise
This exception-driven pattern avoids the check-then-create race in which another process creates the path after os.path.exists() has been checked. Do not assume that an existing path is harmless: a regular file, symlink, junction, or other filesystem object may occupy the name.
For ordinary “create if missing” behavior, these APIs are simpler:
import os
os.makedirs("logs", exist_ok=True)
from pathlib import Path
Path("logs").mkdir(exist_ok=True)
exist_ok=True accepts an existing directory, not an existing regular file.
Missing parent directories
os.mkdir("output/reports") fails with FileNotFoundError when output does not exist. os.mkdir() creates only the final directory entry.
import os
os.makedirs("output/reports", exist_ok=True)
The pathlib equivalent is:
from pathlib import Path
Path("output/reports").mkdir(parents=True, exist_ok=True)
Without parents=True, Path.mkdir() also raises FileNotFoundError for a missing parent. Details are in the os.makedirs() and Path.mkdir() documentation.
Understanding the mode argument
import os
os.mkdir("private_data", mode=0o700)
Octal notation expresses permission bits on POSIX systems:
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 reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minute0o700: owner can read, write, and enter; group and others have no access.0o750: owner has full access; group can read and enter; others have no access.0o755: owner has full access; group and others can read and enter.
These are requests, not guaranteed final permissions. On POSIX systems, the process’s umask removes bits from the requested mode. Some platforms ignore parts of mode. On Windows, Python 3.13 and later specially apply 0o700 as an access-control setting; other mode values are ignored according to the documentation. See the platform notes for os.mkdir().
Handling common exceptions
| Exception | Meaning | Typical response |
|---|---|---|
FileExistsError |
The target name is occupied | Accept it only after confirming it is a directory; otherwise report the collision. |
FileNotFoundError |
A required parent component is missing | Create the tree with os.makedirs() or Path.mkdir(parents=True). |
PermissionError |
The operating system denied creation | Choose a writable parent or correct permissions and policy restrictions. |
NotADirectoryError |
A parent component is a file | Correct, rename, or remove the conflicting file. |
OSError |
Another operating-system filesystem failure | Log the path and inspect the underlying error. |
A focused handler keeps expected failures understandable:
import os
directory = "reports"
try:
os.mkdir(directory)
except FileExistsError:
if not os.path.isdir(directory):
raise
print(f"{directory!r} already exists.")
except FileNotFoundError:
print("The parent directory does not exist.")
except PermissionError:
print("Permission denied.")
For a higher-level API, preserve the original exception context:
import os
try:
os.mkdir("reports")
except OSError as exc:
raise RuntimeError("Could not create reports directory") from exc
Avoid bare except:; it can hide programming errors and interrupts.
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 →Choosing among directory APIs
| API | Best use | Creates parents? | Accepts existing directory? |
|---|---|---|---|
os.mkdir() |
One directory, with an existing target treated as an error | No | No built-in option |
os.makedirs() |
String-based nested directory trees | Yes | exist_ok=True |
Path.mkdir() |
Path-oriented, object-based code | parents=True |
exist_ok=True |
tempfile.mkdtemp() |
Unique temporary directories | Managed by the temporary-directory API | Creates a new unique directory |
Use os.mkdir() when a single final directory and an existing-target error are exactly what you want. Use os.makedirs() for recursive string paths. Choose Path.mkdir() when you compose, resolve, inspect, and pass paths through several operations; its documented alternatives are listed in the pathlib documentation.
Advanced: dir_fd
You can make a path relative to an open directory file descriptor:
import os
parent_fd = os.open("workspace", os.O_RDONLY)
try:
os.mkdir("cache", dir_fd=parent_fd)
finally:
os.close(parent_fd)
This creates cache inside the directory represented by parent_fd. Support is platform-dependent, and the parameter is mainly useful for descriptor-relative filesystem code. It was added in Python 3.3.
User-provided paths and containment
os.mkdir() does not protect an application from absolute paths, .. traversal, symlink behavior, or writes outside an intended base directory. Resolve and validate user input before creation:
Recommended Free Tools
from pathlib import Path
base = Path("/srv/my_app").resolve()
candidate = (base / user_supplied_name).resolve()
if candidate.parent != base:
raise ValueError("Invalid directory name")
candidate.mkdir()
For nested user-controlled paths, use a proper containment test such as candidate.is_relative_to(base) where available, and account for symlink and race conditions. A string-prefix test is not sufficient: /srv/my_app_backup is not inside /srv/my_app.
Best Value
Verifying, removing, and testing
A successful call normally proves creation; an explicit check is useful in demonstrations or tests:
import os
path = "reports"
os.mkdir(path)
assert os.path.isdir(path)
Remove an empty directory with os.rmdir() or Path.rmdir():
import os
os.rmdir("reports")
These operations are not recursive. Recursive deletion uses shutil.rmtree() and should be reserved for deliberately validated targets because it is destructive.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
For isolated tests, use a temporary directory:
import os
import tempfile
with tempfile.TemporaryDirectory() as temp_dir:
target = os.path.join(temp_dir, "test")
os.mkdir(target)
assert os.path.isdir(target)
For application-created temporary directories, see tempfile.mkdtemp().
Production-ready patterns
One directory, existing target is an error
from pathlib import Path
output_dir = Path("output")
try:
output_dir.mkdir()
except FileExistsError:
if not output_dir.is_dir():
raise
Nested, repeatable setup
from pathlib import Path
Path("output/data").mkdir(parents=True, exist_ok=True)
These two patterns make the intended policy explicit: either an existing target is noteworthy, or setup is safely repeatable.
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.

