455

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)?

Henry Ecker
  • 31,792
  • 14
  • 29
  • 50
Phil
  • 6,011
  • 2
  • 17
  • 24

1 Answers1

865

COMMUNITY EDIT:
As question is closed, @David258's answer is written as a comment.

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")

I leave it to the author of this answer to fold this in or remove it as they see fit.


Original answer starts here:

In Python 3.2+, 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")


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.


P i
  • 26,994
  • 34
  • 144
  • 244
Krumelur
  • 29,183
  • 6
  • 73
  • 115
  • 2
    Just had to look past `os.mkdir` and read the documentation on one more function :) – mgilson Sep 20 '12 at 17:09
  • 8
    There is a slightly different approach here: http://stackoverflow.com/a/14364249/1317713 Thoughts? – Leonid Apr 11 '16 at 06:02
  • 2
    Is the inital `if not os.path.exists` needed since the `os.makedirs` uses [EAFP](https://docs.python.org/2/glossary.html#term-eafp)? – Marcel Wilson Aug 16 '17 at 16:37
  • 2
    nice. but be aware you may need to check that the filename contains a path or attempting to create a path with an empty name (eg derived from `baz.txt`) will error `FileNotFoundError: [Errno 2] No such file or directory: ''` Obviously, this will only happen if you are writing into the present working directory. – ErichBSchulz Aug 06 '18 at 00:52
  • 3
    PermissionError: [Errno 13] Permission denied: '/foo' – Ka-Wa Yip Aug 17 '18 at 11:05
  • 1
    @Ka-WaYip `/foo/bar/baz.txt` is just an example. Replace it with the path you wish your file to be created. In linux, the command `pwd` gives you the path to the current working directory. – LoMaPh Sep 16 '19 at 16:55
  • 9
    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")` – David258 Jan 12 '21 at 12:46
  • @David258 Sorry they closed this question so you don't get any karma for your comment that's more useful now than the actual answer. But thanks. – Noumenon Sep 05 '21 at 16:26