Checking a directory’s existence before creating it avoids potential overwriting and protects our application from crashing.
Using os.makedirs() with exists_ok = True (Python (3.2+))
For basic directory creation while checking if it exists in Python, always use the os.makedirs() method with the exists_ok = True argument. It also avoids race conditions, so it is safe in multi-threaded environments.
If you are using , you should use this approach.
The os.makedirs() can also create intermediate directories if they don’t exist.
If the directory exists, then it will throw a FileExistsError exception.
Before creating a directory, our “parent” directory looks like this:
You can see that it’s empty.
Let’s write a program to create a directory inside the above empty directory:
import os dir_path = "parent/child/grandchild" try: os.makedirs(dir_path, exist_ok=True) except OSError as e: print(f"Error: {e}")
The above output screenshot of a file system shows that it created a child directory inside the parent directory and another nested directory called grandchild inside the child directory. That means makedirs() is a recursive function that can be used to create nested directories, too!
You can see that we passed the exist_ok argument, which prevents the function from raising an error by setting it to True even if the directory already exists.
If you rerun this code, it won’t throw any error. However, if you set the exist_ok to False, it throws FileExistsError.
import os dir_path = "parent/child/grandchild" try: os.makedirs(dir_path, exist_ok=False) except OSError as e: print(f"Error: {e}") # Output: Error: [Errno 17] File exists: 'parent/child/grandchild'
So, it is better to set exists_ok to True.
There is still a chance that it will throw an error like FileExistsError or PermissionError:
- If the path is an existing file (not a directory), it will throw FileExistsError.
- If the directory does not have proper permissions, it will throw a PermissionError.
You can pass the “mode=0o777” argument to handle the permission. It works on Unix-style systems like 0o755 for read/write/execute for the owner.
os.makedirs(dir_path, exist_ok=False, mode=0o777)
Bulk directory creation
If you want to create directories in bulk, you should use a for loop with exist_ok=True for efficiency:
import os dir_paths = ["dir1", "dir2/subdir", "dir3"] try: for path in dir_paths: os.makedirs(path, exist_ok=True) except OSError as e: print(f"Error: {e}")
Using pathlib (Python 3.4+)
There is a built-in module called pathlib, which has a Path.mkdir() method that you can use if you use Python version 3.4+. It is more readable and cross-platform.
from pathlib import Path dir_path = Path("parent/child/grandchild") try: dir_path.mkdir(parents=True, exist_ok=True) except FileExistsError: print(f"Error: {dir_path} is a file, not a directory.") except PermissionError as e: print(f"Permission denied: {e}")
In the above code, we passed the parents = True argument, which tells the interpreter to create parent directories if they are missing.
The exist_ok=True argument tells no error if the directory exists.
It also avoids race conditions by default and handles path separators automatically (e.g., \ vs. /).
Also, in this approach, you may face FileExistsError or PermissionError. For that, you have to deal with it manually.
For example, you can use the os.path.isfile() method to check if it is a file. That will handle the FileExistsError.
To handle PermissionError, give proper permission, run the command as an admin, or choose a new path.
Using os.path.exists() and os.makedirs() (Not recommended)
You can use the os.path.exists() method to check the directory’s existence and then use the os.makedirs() function to create it, but it is inefficient and creates a race condition.
Now, you will ask what a race condition is. Well, if you check os.path.exists() function and then create the directory, another process could create/delete the directory in between, leading to unexpected behavior. Within microseconds, another process can create a directory, which causes issues.
So, it is not safe in multi-threaded environments.
Now, you will ask another question:. Where is the need for using this approach, then?
If you have to execute specific logic only if the directory did not exist before creation, you might combine os.path.exists() with the os.makedirs() method.
import os dir_path = "parent/child/grandchild" if not os.path.exists(dir_path): os.makedirs(dir_path) print("Directory created from scratch!") else: print("Directory already existed.") # Output: Directory created from scratch!
That’s it!
SoftBigs
I found this article helpful. Thank you for writing it!
John Davis
Great blog post! I’m glad to see a detailed explanation of how to create a directory if it doesn’t exist in Python. This is a useful technique that I will definitely use in my own projects. Thanks for sharing!