Hogyan hozhatok létre biztonságosan egy beágyazott könyvtárat?

Mi a legelegánsabb módja annak, hogy ellenőrizzük, hogy létezik-e a könyvtár, ahová egy fájlt írunk, és ha nem, akkor hozzuk létre a könyvtárat Python segítségével? Itt van, amit megpróbáltam:

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)

Valahogy kimaradt az os.path.exists (köszönöm kanja, Blair és Douglas). Ez az, ami most van:

def ensure_dir(file_path):
    directory = os.path.dirname(file_path)
    if not os.path.exists(directory):
        os.makedirs(directory)

Van olyan flag a "open" -hoz, ami ezt automatikusan megtörténteti?

Megoldás

Két jó tulajdonságokkal rendelkező választ látok, mindkettőnek van egy-egy apró hibája, ezért elmondom a véleményemet:

path.exists][1], és fontolja meg a [os.makedirs`]2 létrehozását.

import os
if not os.path.exists(directory):
    os.makedirs(directory)

Amint azt a megjegyzésekben és máshol is megjegyeztük, van egy versenyfeltétel – ha a könyvtár az os.path.exists és az os.makedirs hívások között jön létre, az os.makedirs egy OSError hibával fog sikertelenül működni. Sajnos az OSError általános fogása és a folytatás nem bolondbiztos, mivel figyelmen kívül hagyja a könyvtár létrehozásának más tényezők miatti sikertelenségét, például elégtelen jogosultságok, tele lemez stb. miatt.

Az egyik lehetőség az OSError csapdába ejtése és a beágyazott hibakód vizsgálata lenne (lásd Is there a cross-platform way of getting information from Python's OSError):

import os, errno

try:
    os.makedirs(directory)
except OSError as e:
    if e.errno != errno.EEXIST:
        raise

Alternatív megoldás lehet egy második os.path.exists, de tegyük fel, hogy egy másik létrehozta a könyvtárat az első ellenőrzés után, majd eltávolította a második ellenőrzés előtt – még mindig becsaphatnak minket.

Az alkalmazástól függően az egyidejű műveletek veszélye nagyobb vagy kisebb lehet, mint az egyéb tényezők, például a fájljogosultságok által jelentett veszély. A fejlesztőnek többet kellene tudnia az adott fejlesztendő alkalmazásról és annak várható környezetéről, mielőtt kiválasztja a megvalósítást.

A Python modern verziói elég sokat javítanak ezen a kódon, mind a FileExistsError (a 3.3+ verzióban), mind a FileExistsError[5][6][7][7][7][7][7]...

try:
    os.makedirs("path/to/directory")
except FileExistsError:
    # directory already exists
    pass

...és azáltal, hogy lehetővé teszi az os.makedirs kulcsszavas argumentumát, az exist_ok-t (a 3.2+ verzióban).

os.makedirs("path/to/directory", exist_ok=True)  # succeeds even if directory exists.
Kommentárok (8)

Ellenőrizze os.makedirs: (Biztosítja, hogy a teljes elérési útvonal létezik.) Annak kezelésére, hogy a könyvtár esetleg létezik, a OSError fogása. (Ha az exist_ok értéke False (alapértelmezett), akkor OSError jelzést kap, ha a célkönyvtár már létezik.)

import os
try:
    os.makedirs('./path/to/somewhere')
except OSError:
    pass
Kommentárok (3)

Próbálja ki az os.path.exists függvényt.

if not os.path.exists(dir):
    os.mkdir(dir)
Kommentárok (3)