What is the most elegant way to check if the directory a file is going to be written to exists, and if not, create the directory using Python? Here is what I tried:
import os
file_path = "/my/directory/filename.txt"
directory = os.path.dirname(file_path)
try:
os.stat(directory)
except:
os.mkdir(directory)
f = file(filename)
Somehow, I missed os.path.exists
(thanks kanja, Blair, and Douglas). This is what I have now:
def ensure_dir(file_path):
directory = os.path.dirname(file_path)
if not os.path.exists(directory):
os.makedirs(directory)
Is there a flag for "open", that makes this happen automatically?
Using try except and the right error code from errno module gets rid of the race condition and is cross-platform:
In other words, we try to create the directories, but if they already exist we ignore the error. On the other hand, any other error gets reported. For example, if you create dir 'a' beforehand and remove all permissions from it, you will get an
OSError
raised witherrno.EACCES
(Permission denied, error 13).I have put the following down. It's not totally foolproof though.
Now as I say, this is not really foolproof, because we have the possiblity of failing to create the directory, and another process creating it during that period.
The relevant Python documentation suggests the use of the EAFP coding style (Easier to Ask for Forgiveness than Permission). This means that the code
is better than the alternative
The documentation suggests this exactly because of the race condition discussed in this question. In addition, as others mention here, there is a performance advantage in querying once instead of twice the OS. Finally, the argument placed forward, potentially, in favour of the second code in some cases --when the developer knows the environment the application is running-- can only be advocated in the special case that the program has set up a private environment for itself (and other instances of the same program).
Even in that case, this is a bad practice and can lead to long useless debugging. For example, the fact we set the permissions for a directory should not leave us with the impression permissions are set appropriately for our purposes. A parent directory could be mounted with other permissions. In general, a program should always work correctly and the programmer should not expect one specific environment.
For a one-liner solution, you can use
IPython.utils.path.ensure_dir_exists()
:From the documentation: Ensure that a directory exists. If it doesn’t exist, try to create it and protect against a race condition if another process is doing the same.
When working with file I/O, the important thing to consider is
TOCTTOU (time of check to time of use)
So doing a check with
if
and then reading or writing later may end up in an unhandled I/O exception. The best way to do it is:I found this Q/A and I was initially puzzled by some of the failures and errors I was getting. I am working in Python 3 (v.3.5 in an Anaconda virtual environment on an Arch Linux x86_64 system).
Consider this directory structure:
Here are my experiments/notes, which clarifies things:
Conclusion: in my opinion, "Method 2" is more robust.
[1] How can I create a directory if it does not exist?
[2] https://docs.python.org/3/library/os.html#os.makedirs