Hoe kan ik veilig een geneste map maken?

Wat is de meest elegante manier om te controleren of de directory waar een bestand naar toe geschreven moet worden bestaat, en zo niet, de directory aan te maken met Python? Dit is wat ik geprobeerd heb:

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)

Op de een of andere manier miste ik os.path.exists (bedankt kanja, Blair, en Douglas). Dit is wat ik nu heb:

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

Is er een vlag voor "open", die dit automatisch laat gebeuren?

Oplossing

Ik zie twee antwoorden met goede kwaliteiten, elk met een klein minpuntje, dus ik zal er mijn mening over geven:

Probeer os.path.exists, en overweeg os.makedirs voor de creatie.

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

Zoals opgemerkt in commentaren en elders, is er een race conditie – als de directory wordt aangemaakt tussen de os.path.exists en de os.makedirs calls, zal de os.makedirs falen met een OSError. Helaas is het niet waterdicht om de OSError af te vangen en verder te gaan, omdat het falen om de map aan te maken door andere factoren, zoals onvoldoende rechten, volle schijf, enz. wordt genegeerd.

Een optie zou zijn om de OSError te vangen en de ingesloten foutcode te onderzoeken (zie 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

Als alternatief zou er een tweede os.path.exists kunnen zijn, maar stel dat een ander de directory na de eerste controle heeft aangemaakt, en hem vervolgens voor de tweede heeft verwijderd – we zouden nog steeds voor de gek gehouden kunnen worden.

Afhankelijk van de toepassing, kan het gevaar van gelijktijdige bewerkingen meer of minder zijn dan het gevaar van andere factoren zoals bestandspermissies. De ontwikkelaar zou meer moeten weten over de specifieke toepassing die wordt ontwikkeld en de verwachte omgeving voordat hij een implementatie kiest.

Moderne versies van Python verbeteren deze code behoorlijk, zowel door het blootleggen van FileExistsError (in 3.3+)...

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

...en door een sleutelwoord argument aan os.makedirs genaamd exist_ok toe te staan (in 3.2+).

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

Controleer os.makedirs: (Het zorgt ervoor dat het volledige pad bestaat.) Om om te gaan met het feit dat de directory misschien bestaat, vang OSError. (Als exist_ok False is (de standaard), wordt een OSError opgewekt als de doelmap al bestaat).

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

Probeer de os.path.exists functie

if not os.path.exists(dir):
    os.mkdir(dir)
Commentaren (3)