Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

os.mkdir() creates exactly one new directory. Its parent must already exist, and the target path must not be occupied. The basic call is:

import os

os.mkdir("reports")

On success, the function returns None. For nested paths or an existing-directory-safe operation, use os.makedirs() or pathlib.Path.mkdir() instead.

Syntax and behavior

The documented signature is os.mkdir(path, mode=0o777, *, dir_fd=None).

  • path is the directory name or path to create. Strings, bytes, and path-like objects such as pathlib.Path are accepted.
  • mode requests permission bits on platforms that support them.
  • dir_fd optionally makes a relative path resolve from an open directory file descriptor.

os.mkdir() does not create files, add content, or create missing parent directories.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Creating a directory with a relative or absolute path

Relative paths

A relative path is interpreted from the process’s current working directory, not automatically from the directory containing your Python file.

import os

print(os.getcwd())
os.mkdir("logs")

If the program is launched from a different directory, logs will be created there. To create a directory beside the script, use its resolved location 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, escaped backslashes, or a Path:

import os

os.mkdir(r"C:UsersAliceDocumentslogs")
os.mkdir("C:\Users\Alice\Documents\logs")
from pathlib import Path

Path(r"C:UsersAliceDocumentslogs").mkdir()

What happens when the target already exists?

The second call below raises FileExistsError:

import os

os.mkdir("logs")
os.mkdir("logs")

os.mkdir() has no exist_ok parameter. If an existing directory is acceptable, use an API that supports that policy:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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 or other incompatible filesystem object.

For a single-directory operation that must tolerate an existing directory while rejecting a file collision:

import os

try:
    os.mkdir("logs")
except FileExistsError:
    if not os.path.isdir("logs"):
        raise

A check followed by creation, such as if not os.path.exists(...): os.mkdir(...), is race-prone: another process can create the path between those two operations.

Creating nested directories

os.mkdir("output/reports") fails with FileNotFoundError when output does not already exist. Use os.makedirs() for a directory tree:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import os

os.makedirs("output/2026/august", exist_ok=True)

The exist_ok=True option makes the operation idempotent when the complete path is already a directory.

The equivalent object-oriented form is:

from pathlib import Path

Path("output/2026/august").mkdir(parents=True, exist_ok=True)

Without parents=True, Path.mkdir() also raises FileNotFoundError when a parent is missing.

Understanding the mode argument

import os

os.mkdir("private_data", mode=0o700)

On POSIX systems, the requested mode is combined with the process’s umask, so 0o777 is not necessarily the final permission set. The final three octal digits represent owner, group, and other permissions:

Mode Typical POSIX meaning
0o700 Owner can read, write, and enter; group and others have no access.
0o755 Owner has full access; group and others can read and enter.
0o750 Owner has full access; group can read and enter; others have no access.

Permission semantics are platform-dependent. Some systems ignore parts of mode. On Windows, Python 3.13 and later specifically apply 0o700 as an access-control setting for a new directory; other mode values are ignored according to the Python documentation. Do not assume that 0o700 produces identical behavior everywhere.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Handling common exceptions

Exception Meaning Typical response
FileExistsError The target is already occupied. Accept it only if it is a directory; otherwise report the collision.
FileNotFoundError A required parent component is missing. Create the parent tree with os.makedirs() or Path.mkdir(parents=True).
PermissionError The operating system denied the operation. Choose a writable location or correct the applicable permissions and policy.
NotADirectoryError A parent component is a regular file. Correct, rename, or remove the conflicting path.
OSError Another operating-system filesystem failure occurred. Inspect the original error and the path involved.
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.")

Avoid a bare except:; it can hide interrupts and programming errors. When adding application context, preserve the original exception:

import os

try:
    os.mkdir("reports")
except OSError as exc:
    raise RuntimeError("Could not create reports directory") from exc

Advanced: creating relative to a directory descriptor

dir_fd is optional and platform-dependent. It is useful when low-level code needs filesystem operations relative to an already opened directory:

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. The parameter was added in Python 3.3 and is not needed for ordinary scripts.

Choosing among directory APIs

API Best fit Creates missing parents? Existing-target option
os.mkdir() One directory, with an existing target treated as an error. No No exist_ok parameter
os.makedirs() String-based nested directory trees. Yes exist_ok=True
Path.mkdir() Path-heavy, object-oriented code. With parents=True exist_ok=True
tempfile.mkdtemp() Unique temporary directories. Creates a temporary directory Designed to avoid name collisions

Use os.mkdir() when the parent is guaranteed to exist and the direct operating-system primitive is what you need. Prefer os.makedirs() for recursive string paths and Path.mkdir() when paths are composed, resolved, and inspected throughout the program. For temporary work, use tempfile.mkdtemp() rather than a predictable hand-built name.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Production patterns and verification

Single directory with an explicit collision policy

from pathlib import Path

output_dir = Path("output")

try:
    output_dir.mkdir()
except FileExistsError:
    if not output_dir.is_dir():
        raise

Idempotent nested setup

from pathlib import Path

data_dir = Path("project") / "data" / "raw"
data_dir.mkdir(parents=True, exist_ok=True)

Successful completion without an exception is normally sufficient evidence that creation worked. In demonstrations or tests, verify explicitly:

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)

Path safety with user input

The API itself does not prevent absolute paths, .. traversal, symlink surprises, or creation outside an intended base directory. Resolve and validate user-controlled paths before creating them:

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 containment test such as candidate.is_relative_to(base) where supported, and account for symlink and race conditions. A string prefix test is not sufficient: /srv/my_app_backup is not inside /srv/my_app.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Removing a directory

os.rmdir() removes an empty directory:

import os

os.rmdir("reports")

It is not recursive. Removing a non-empty directory requires shutil.rmtree(), which permanently deletes a directory tree and should be used only after carefully validating the target.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Frequently Asked Questions

Does os.mkdir() create parent directories?

No. It creates only the final directory. Use os.makedirs(path, exist_ok=True) or Path(path).mkdir(parents=True, exist_ok=True) for missing parents.

How do I avoid FileExistsError?

Use os.makedirs(…, exist_ok=True) or Path.mkdir(exist_ok=True) when an existing directory is acceptable. Neither treats an existing regular file as a directory.

Why was the directory created in the wrong location?

Relative paths use the process’s current working directory. Inspect it with os.getcwd(), or build a path from Path(__file__).resolve().parent.

How do I create a temporary directory?

Use tempfile.mkdtemp(), which is intended to produce a uniquely named temporary directory.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.