Jaki jest najbardziej elegancki sposób na sprawdzenie, czy katalog, do którego ma być zapisany plik, istnieje, a jeśli nie, utworzenie katalogu za pomocą Pythona? Oto, co próbowałem:
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)
W jakiś sposób przegapiłem os.path.exists
(dzięki kanja, Blair i Douglas). To jest to, co mam teraz:
def ensure_dir(file_path):
directory = os.path.dirname(file_path)
if not os.path.exists(directory):
os.makedirs(directory)
Czy jest jakaś flaga dla "open", która sprawia, że dzieje się to automatycznie?
Widzę dwie odpowiedzi z dobrymi cechami, każda z małą wadą, więc dam moje ujęcie na ten temat:
Spróbuj os.path.exists
, i rozważ os.makedirs
do tworzenia.
import os
if not os.path.exists(directory):
os.makedirs(directory)
Jak zauważono w komentarzach i gdzie indziej, istnieje warunek wyścigu – jeśli katalog zostanie utworzony pomiędzy wywołaniami os.path.exists
i os.makedirs
, os.makedirs
zawiedzie z OSError
. Niestety, wyłapywanie OSError
i kontynuowanie nie jest niezawodne, ponieważ zignoruje niepowodzenie tworzenia katalogu z powodu innych czynników, takich jak niewystarczające uprawnienia, pełny dysk, itp.
Jedną z opcji byłoby złapanie OSError
i zbadanie osadzonego kodu błędu (zobacz Czy istnieje międzyplatformowy sposób na uzyskanie informacji z Python's OSError):
import os, errno
try:
os.makedirs(directory)
except OSError as e:
if e.errno != errno.EEXIST:
raise
Alternatywnie, może być drugi os.path.exists
, ale załóżmy, że inny utworzył katalog po pierwszym sprawdzeniu, a następnie usunął go przed drugim – nadal możemy zostać oszukani.
W zależności od aplikacji, niebezpieczeństwo współbieżnych operacji może być większe lub mniejsze niż niebezpieczeństwo stwarzane przez inne czynniki, takie jak uprawnienia do plików. Programista musiałby wiedzieć więcej o konkretnej tworzonej aplikacji i jej oczekiwanym środowisku przed wyborem implementacji.
Współczesne wersje Pythona dość mocno poprawiają ten kod, zarówno poprzez wyeksponowanie FileExistsError
(w wersji 3.3+)...
try:
os.makedirs("path/to/directory")
except FileExistsError:
# directory already exists
pass
...i przez umożliwienie argumentu słowa kluczowego do os.makedirs
o nazwie exist_ok
(w 3.2+).
os.makedirs("path/to/directory", exist_ok=True) # succeeds even if directory exists.
Sprawdź os.makedirs
: (Upewnia się, że kompletna ścieżka istnieje).
Aby obsłużyć fakt, że katalog może istnieć, złap OSError
.
(Jeśli exist_ok
jest False
(domyślnie), to OSError
jest podnoszony jeśli katalog docelowy już istnieje).
import os
try:
os.makedirs('./path/to/somewhere')
except OSError:
pass
Spróbuj funkcji os.path.exists
if not os.path.exists(dir):
os.mkdir(dir)