559

Say I want to make a file:

filename = "/foo/bar/baz.txt"

with open(filename, "w") as f:
    f.write("FOOBAR")

This gives an IOError, since /foo/bar does not exist.

What is the most pythonic way to generate those directories automatically? Is it necessary for me explicitly call os.path.exists and os.mkdir on every single one (i.e., /foo, then /foo/bar)?

0

1 Answer 1

1053

In Python 3.2+, using the APIs requested by the OP, you can elegantly do the following:


import os

filename = "/foo/bar/baz.txt"
os.makedirs(os.path.dirname(filename), exist_ok=True)
with open(filename, "w") as f:
    f.write("FOOBAR")


With the Pathlib module (introduced in Python 3.4), there is an alternate syntax (thanks David258):

from pathlib import Path
output_file = Path("/foo/bar/baz.txt")
output_file.parent.mkdir(exist_ok=True, parents=True)
output_file.write_text("FOOBAR")

In older python, there is a less elegant way:

The os.makedirs function does this. Try the following:

import os
import errno

filename = "/foo/bar/baz.txt"
if not os.path.exists(os.path.dirname(filename)):
    try:
        os.makedirs(os.path.dirname(filename))
    except OSError as exc: # Guard against race condition
        if exc.errno != errno.EEXIST:
            raise

with open(filename, "w") as f:
    f.write("FOOBAR")

The reason to add the try-except block is to handle the case when the directory was created between the os.path.exists and the os.makedirs calls, so that to protect us from race conditions.


Sign up to request clarification or add additional context in comments.

8 Comments

Just had to look past os.mkdir and read the documentation on one more function :)
There is a slightly different approach here: stackoverflow.com/a/14364249/1317713 Thoughts?
Is the inital if not os.path.exists needed since the os.makedirs uses EAFP?
PermissionError: [Errno 13] Permission denied: '/foo'
with Pathlib: from pathlib import Path; output_file = Path("/foo/bar/baz.txt"); output_file.parent.mkdir(exist_ok=True, parents=True); output_file.write_text("FOOBAR")
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.