Bagaimana saya dapat dengan aman membuat list direktori?

Apa adalah cara yang paling elegan untuk memeriksa apakah direktori file yang akan ditulis untuk ada, dan jika tidak, membuat direktori menggunakan Python? Berikut adalah apa yang saya coba:

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)

Entah bagaimana, aku rindu os.jalan.ada (terima kasih kanja, Blair, dan Douglas). Ini adalah apa yang saya miliki sekarang:

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

Ada sebuah bendera untuk "terbuka", yang membuat hal ini terjadi secara otomatis?

Mengomentari pertanyaan (6)
Larutan

Saya melihat dua jawaban dengan kualitas yang baik, masing-masing dengan cacat kecil, jadi saya akan memberikan saya mengambil itu:

Mencoba os.jalan.ada, dan mempertimbangkan os.makedirs untuk penciptaan.

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

Seperti dicatat di komentar dan di tempat lain, ada's kondisi balapan – jika direktori yang dibuat antara os.jalan.ada dan os.makedirs panggilan, os.makedirs akan gagal dengan OSError. Sayangnya, selimut-catching OSError dan melanjutkan ini tidaklah mudah, karena akan mengabaikan kegagalan untuk membuat direktori karena faktor-faktor lain, seperti izin tidak cukup, disk, dll.

Salah satu pilihan akan menghentikan OSError dan memeriksa tertanam kode kesalahan (lihat ada cross-platform cara untuk mendapatkan informasi dari Python OSError):

import os, errno

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

Atau, mungkin ada yang kedua os.jalan.ada, tapi misalkan lain dibuat direktori setelah periksa dulu, kemudian dihapus sebelum yang kedua – kita masih bisa tertipu.

Tergantung pada aplikasi, bahaya bersamaan operasi mungkin lebih atau kurang dari bahaya yang ditimbulkan oleh faktor-faktor lain seperti file permissions. Pengembang akan memiliki untuk tahu lebih lanjut tentang aplikasi yang sedang dikembangkan dan diharapkan lingkungan sebelum memilih sebuah implementasi.

Versi Modern dari Python meningkatkan kode ini cukup sedikit, baik dengan mengekspos FileExistsError (in 3.3+)...

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

...dan dengan memungkinkan kata kunci argumen untuk os.makedirs disebut exist_ok (3,2+).

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

Python 3.5+:

import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True) 

pathlib.Jalan.mkdir seperti yang digunakan di atas secara rekursif menciptakan direktori dan tidak menaikkan pengecualian jika direktori yang sudah ada. Jika anda don't perlu atau ingin para orang tua yang akan dibuat, loncat orang tua argumen.

Python 3.2+:

Menggunakan pathlib:

Jika anda bisa, menginstal saat ini pathlib backport bernama pathlib2. Jangan memasang lebih tua terawat backport bernama pathlib. Selanjutnya, merujuk pada Python 3.5+ bagian atas dan menggunakan hal yang sama.

Jika menggunakan Python 3.4, meskipun itu datang dengan pathlib, itu hilang berguna exist_ok pilihan. Yang backport ini dimaksudkan untuk menawarkan baru dan segala pelaksanaan mkdir yang hilang opsi.

Menggunakan os:

import os
os.makedirs(path, exist_ok=True)

os.makedirs seperti yang digunakan di atas secara rekursif menciptakan direktori dan tidak menaikkan pengecualian jika direktori yang sudah ada. Memiliki optional exist_ok argumen hanya jika menggunakan Python 3.2+, dengan nilai default Palsu. Argumen ini tidak ada di Python 2.x hingga 2.7. Dengan demikian, tidak ada kebutuhan untuk manual exception handling seperti dengan Python 2.7.

Python 2.7+:

Menggunakan pathlib:

Jika anda bisa, menginstal saat ini pathlib backport bernama pathlib2. Jangan memasang lebih tua terawat backport bernama pathlib. Selanjutnya, merujuk pada Python 3.5+ bagian atas dan menggunakan hal yang sama.

Menggunakan os:

import os
try: 
    os.makedirs(path)
except OSError:
    if not os.path.isdir(path):
        raise

Sementara solusi naif mungkin penggunaan pertama os.jalan.isdir diikuti dengan os.makedirs, solusi atas membalikkan urutan dua operasi. Dalam melakukannya, hal ini mencegah umum kondisi balapan yang berhubungan dengan duplikasi upaya menciptakan direktori, dan juga disambiguates file dari direktori.

Perhatikan bahwa menangkap pengecualian dan menggunakan errno adalah kegunaan terbatas karena OSError: [Errno 17] File yang ada, yaitu errno.EEXIST, dibesarkan untuk kedua file dan direktori. Hal ini lebih handal hanya untuk memeriksa apakah ada direktori.

Alternatif:

mkpath menciptakan bersarang direktori, dan tidak apa-apa jika direktori yang sudah ada. Ini bekerja di kedua Python 2 dan 3.

import distutils.dir_util
distutils.dir_util.mkpath(path)

Per Bug 10948, keterbatasan parah dari alternatif ini adalah bahwa ia bekerja hanya sekali per python proses untuk mengingat jalan. Dengan kata lain, jika anda menggunakannya untuk membuat sebuah direktori, kemudian menghapus direktori dari dalam atau luar Python, maka menggunakan mkpath lagi untuk menciptakan direktori yang sama, mkpath hanya akan diam-diam penggunaan yang tidak sah cache info setelah sebelumnya membuat direktori, dan tidak akan benar-benar membuat direktori lagi. Sebaliknya, os.makedirs doesn't bergantung pada setiap cache seperti. Keterbatasan ini mungkin baik-baik saja untuk beberapa aplikasi.


Berkaitan dengan direktori's modus, silakan merujuk ke dokumentasi jika anda peduli tentang hal itu.

Komentar (10)

Menggunakan cobalah kecuali dan kanan kode kesalahan dari errno modul menghilangkan kondisi ras dan cross-platform:

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise

Dengan kata lain, kita mencoba untuk membuat direktori, tetapi jika mereka sudah ada kita mengabaikan kesalahan. Di sisi lain, setiap kesalahan akan dilaporkan. Misalnya, jika anda membuat dir 'a' sebelumnya dan menghapus semua izin dari itu, anda akan mendapatkan sebuah OSError dibesarkan errno.EACCES (Izin ditolak, kesalahan 13).

Komentar (20)

Saya pribadi akan merekomendasikan bahwa anda menggunakan os.jalan.isdir()untuk menguji bukanos.jalan.ada()`.

>>> os.path.exists('/tmp/dirname')
True
>>> os.path.exists('/tmp/dirname/filename.etc')
True
>>> os.path.isdir('/tmp/dirname/filename.etc')
False
>>> os.path.isdir('/tmp/fakedirname')
False

Jika anda memiliki:

>>> dir = raw_input(":: ")

Dan bodoh input pengguna:

:: /tmp/dirname/filename.etc

... Anda're akan berakhir dengan sebuah direktori bernama nama berkas.dll ketika anda melewati argumen itu untuk os.makedirs() jika anda menguji dengan os.jalan.ada().

Komentar (3)

Cek os.makedirs: (Itu membuat yakin path lengkap ada.) Untuk menangani fakta direktori mungkin ada, menangkap OSError. (Jika exist_ok adalah Palsu (default), OSError dinaikkan jika target direktori yang sudah ada.)

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

Mulai dari Python 3.5, pathlib.Jalan.mkdir memiliki exist_ok bendera:

from pathlib import Path
path = Path('/my/directory/filename.txt')
path.parent.mkdir(parents=True, exist_ok=True) 
# path.parent ~ os.path.dirname(path)

Hal ini secara rekursif menciptakan direktori dan tidak menaikkan pengecualian jika direktori yang sudah ada.

(hanya sebagai os.makedirs mendapat exist_ok bendera mulai dari python 3.2 e.g os.makedirs(jalan, exist_ok=True))

Komentar (0)

Wawasan tentang spesifik dari situasi ini

Anda memberikan file tertentu pada jalur tertentu dan anda menarik direktori dari path file. Kemudian setelah memastikan anda memiliki direktori, anda mencoba untuk membuka file untuk membaca. Komentar pada kode ini:

filename = "/saya/direktori/file.txt" dir = os.jalan.dirname(filename)

Kami ingin menghindari timpa fungsi bawaan, dir. Juga, path file atau mungkin fullfilepath mungkin adalah yang lebih baik semantik nama dari filename jadi ini akan menjadi lebih baik ditulis:

import os
filepath = '/my/directory/filename.txt'
directory = os.path.dirname(filepath)

Tujuan akhir anda adalah untuk membuka file ini, anda awalnya negara, untuk menulis, tapi anda're pada dasarnya mendekati tujuan ini (berdasarkan kode) seperti ini, yang membuka file untuk membaca:

jika tidak os.jalan.ada(direktori): os.makedirs(direktori) f = file(nama file)

Dengan asumsi pembukaan untuk membaca

Mengapa anda membuat sebuah direktori untuk file yang anda berharap untuk berada di sana dan bisa membaca?

Hanya mencoba untuk membuka file.

with open(filepath) as my_file:
    do_stuff(my_file)

Jika direktori atau file isn't ada, anda'll mendapatkan IOError dengan kesalahan terkait nomor: errno.ENOENT akan arahkan untuk memperbaiki kesalahan nomor terlepas dari platform. Anda dapat menangkap itu jika anda ingin, misalnya:

import errno
try:
    with open(filepath) as my_file:
        do_stuff(my_file)
except IOError as error:
    if error.errno == errno.ENOENT:
        print 'ignoring error because directory or file is not there'
    else:
        raise

Dengan asumsi kita're pembukaan untuk menulis

Ini adalah mungkin apa yang anda're menginginkan.

Dalam hal ini, kita mungkin tidak't menghadapi setiap kondisi ras. Jadi lakukan saja seperti anda, tetapi perhatikan bahwa untuk menulis, anda perlu membuka dengan w mode (atau a untuk menambahkan). It's juga Python praktek terbaik untuk menggunakan konteks manager untuk membuka file.

import os
if not os.path.exists(directory):
    os.makedirs(directory)
with open(filepath, 'w') as my_file:
    do_stuff(my_file)

Namun, katakanlah kita memiliki beberapa Python proses yang mencoba untuk menempatkan semua data ke dalam direktori yang sama. Kemudian kita mungkin memiliki perselisihan atas penciptaan direktori. Dalam kasus itu's terbaik untuk membungkus makedirs panggilan di coba-kecuali blok.

import os
import errno
if not os.path.exists(directory):
    try:
        os.makedirs(directory)
    except OSError as error:
        if error.errno != errno.EEXIST:
            raise
with open(filepath, 'w') as my_file:
    do_stuff(my_file)
Komentar (0)

Mencoba os.jalan.ada fungsi

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

Saya telah menempatkan berikut turun. It's tidak benar-benar bodoh sekalipun.

import os

dirname = 'create/me'

try:
    os.makedirs(dirname)
except OSError:
    if os.path.exists(dirname):
        # We are nearly safe
        pass
    else:
        # There was an error on creation, so make sure we know about it
        raise

Sekarang seperti yang saya katakan, ini bukan benar-benar sangat mudah, karena kami memiliki possiblity gagal untuk membuat direktori, dan proses lain yang menciptakan itu selama periode itu.

Komentar (2)

Periksa apakah ada direktori dan membuat itu jika diperlukan?

Jawaban langsung untuk ini adalah, dengan asumsi situasi yang sederhana di mana anda don't mengharapkan pengguna lain atau proses yang akan bermain-main dengan direktori anda:

if not os.path.exists(d):
    os.makedirs(d)

atau jika membuat direktori adalah tunduk pada kondisi ras (yaitu jika setelah memeriksa jalan yang ada, sesuatu yang lain mungkin sudah membuatnya) melakukan hal ini:

import errno
try:
    os.makedirs(d)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise

Tapi mungkin pendekatan yang lebih baik adalah dengan menghindari sumber pertikaian masalah, dengan menggunakan direktori sementara melalui file temp:

import tempfile

d = tempfile.mkdtemp()

Berikut ini's the essentials dari online doc:

mkdtemp(akhiran='', prefix='tmp', dir=Tidak ada) User-callable fungsi untuk membuat dan kembali sementara yang unik direktori. Nilai kembali adalah path dari direktori.

direktori yang bisa dibaca, ditulis, dan dilakukan hanya oleh membuat user.

Caller yang bertanggung jawab untuk menghapus direktori bila dilakukan dengan itu.

Baru di Python 3.5: pathlib.Jalan dengan exist_ok

Ada's baru Path objek (seperti 3.4) dengan banyak metode yang ingin digunakan dengan jalur - salah satu yang mkdir.

(Untuk konteks, I'm pelacakan mingguan saya rep dengan script. Berikut ini's bagian yang relevan dari kode script yang memungkinkan saya untuk menghindari memukul Stack Overflow lebih dari sekali sehari untuk data yang sama.)

Pertama terkait impor:

from pathlib import Path
import tempfile

Kami don't harus berurusan dengan os.jalan.bergabung sekarang - hanya bergabung dengan path bagian dengan/`:

directory = Path(tempfile.gettempdir()) / 'sodata'

Kemudian saya idempotently memastikan ada direktori - the exist_ok argumen muncul di Python 3.5:

directory.mkdir(exist_ok=True)

Berikut ini's bagian yang relevan dari dokumentasi:

Jika exist_ok benar, FileExistsError pengecualian akan diabaikan (perilaku yang sama sebagai POSIX mkdir -p perintah), tetapi hanya jika jalan terakhir komponen tidak ada non-direktori file.

Berikut ini's lebih sedikit dari the script - dalam kasus saya, saya'm tidak tunduk pada kondisi balapan, saya hanya memiliki satu proses yang mengharapkan direktori (atau terdapat file) untuk berada di sana, dan saya don't memiliki apa-apa mencoba untuk menghapus direktori.

todays_file = directory / str(datetime.datetime.utcnow().date())
if todays_file.exists():
    logger.info("todays_file exists: " + str(todays_file))
    df = pd.read_json(str(todays_file))

Path benda harus dipaksa untuk str sebelum Api lainnya yang mengharapkan str jalan dapat menggunakannya.

Mungkin Panda harus diperbarui untuk menerima contoh abstrak kelas dasar, os.PathLike.

Komentar (0)

Di Python 3.4 anda juga dapat menggunakan baru pathlib module:

from pathlib import Path
path = Path("/my/directory/filename.txt")
try:
    if not path.parent.exists():
        path.parent.mkdir(parents=True)
except OSError:
    # handle error; you can also catch specific errors like
    # FileExistsError and so on.
Komentar (2)

The relevan dokumentasi Python menunjukkan penggunaan EAFP coding style (lebih Mudah untuk Meminta Pengampunan dari Izin). Ini berarti bahwa kode

try:
    os.makedirs(path)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise
    else:
        print "\nBE CAREFUL! Directory %s already exists." % path

adalah lebih baik daripada alternatif

if not os.path.exists(path):
    os.makedirs(path)
else:
    print "\nBE CAREFUL! Directory %s already exists." % path

Dokumentasi ini menunjukkan persis karena kondisi balapan yang dibahas dalam pertanyaan ini. Selain itu, sebagai orang lain lagi di sini, ada keuntungan kinerja dalam query satu kali, bukan dua kali OS. Akhirnya, argumen ditempatkan ke depan, berpotensi, dalam mendukung kode kedua dalam beberapa kasus --ketika pengembang tahu lingkungan aplikasi berjalan-- hanya dapat menganjurkan dalam kasus khusus bahwa program telah menyiapkan lingkungan pribadi untuk dirinya sendiri (dan contoh-contoh lain dari program yang sama).

Bahkan dalam kasus itu, ini adalah praktek yang buruk dan dapat menyebabkan lama tidak berguna debugging. Misalnya, fakta kita mengatur hak akses untuk direktori tidak harus meninggalkan kami dengan kesan izin diatur dengan tepat untuk tujuan kita. Direktori induk dapat dipasang dengan izin lainnya. Pada umumnya, sebuah program harus selalu bekerja dengan benar dan programmer tidak harus mengharapkan satu lingkungan tertentu.

Komentar (0)

Di Python3, os.makedirs mendukung pengaturan exist_ok. Pengaturan default adalah False, yang berarti OSError akan dibangkitkan jika target direktori yang sudah ada. Dengan menetapkan exist_ok ke True, OSError (ada direktori) akan diabaikan dan direktori tidak akan dibuat.

os.makedirs(path,exist_ok=True)

Di Python2, os.makedirs doesn't dukungan pengaturan exist_ok. Anda dapat menggunakan pendekatan heikki-toivonen's jawaban:

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise
Komentar (0)

Anda dapat menggunakan mkpath

# Create a directory and any missing ancestor directories. 
# If the directory already exists, do nothing.

from distutils.dir_util import mkpath
mkpath("test")    

Perhatikan bahwa itu akan membuat nenek moyang direktori juga.

Ia bekerja untuk Python versi 2 dan 3.

Komentar (2)

Untuk satu kapal solusinya, anda dapat menggunakan IPython.utils.path.ensure_dir_exists():

from IPython.utils.path import ensure_dir_exists
ensure_dir_exists(dir)

Dari dokumentasi: Ensure bahwa direktori yang ada. Jika tidak ada, cobalah untuk menciptakan dan melindungi terhadap kondisi balapan jika proses lain melakukan hal yang sama.

Komentar (3)

Saya menggunakan os.jalan.ada(), di sini adalah Python 3 script yang dapat digunakan untuk memeriksa apakah ada direktori, membuat satu jika itu tidak ada, dan menghapusnya jika sudah tidak ada (jika diinginkan).

Ia meminta pengguna untuk input dari direktori dan dapat dengan mudah dimodifikasi.

Komentar (0)

Anda dapat menggunakan os.listdir ini:

import os
if 'dirName' in os.listdir('parentFolderPath')
    print('Directory Exists')
Komentar (1)

Aku melihat Heikki Toivonen dan A-B-B's jawaban dan pemikiran dari variasi ini.

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST or not os.path.isdir(path):
            raise
Komentar (0)

Saya menemukan ini Q/A dan awalnya saya bingung dengan beberapa kegagalan dan kesalahan saya mendapatkan. Saya bekerja di Python 3 (v. 3.5 di Anaconda lingkungan virtual pada Arch Linux x86_64 system).

Pertimbangkan struktur direktori ini:

└── output/         ## dir
   ├── corpus       ## file
   ├── corpus2/     ## dir
   └── subdir/      ## dir

Berikut ini adalah percobaan saya/catatan, yang menjelaskan hal-hal:

# ----------------------------------------------------------------------------
# [1] https://stackoverflow.com/questions/273192/how-can-i-create-a-directory-if-it-does-not-exist

import pathlib

""" Notes:
        1.  Include a trailing slash at the end of the directory path
            ("Method 1," below).
        2.  If a subdirectory in your intended path matches an existing file
            with same name, you will get the following error:
            "NotADirectoryError: [Errno 20] Not a directory:" ...
"""
# Uncomment and try each of these "out_dir" paths, singly:

# ----------------------------------------------------------------------------
# METHOD 1:
# Re-running does not overwrite existing directories and files; no errors.

# out_dir = 'output/corpus3'                ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/'               ## works
# out_dir = 'output/corpus3/doc1'           ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/doc1/'          ## works
# out_dir = 'output/corpus3/doc1/doc.txt'   ## no error but no file created (os.makedirs creates dir, not files!  ;-)
# out_dir = 'output/corpus2/tfidf/'         ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/'         ## works
# out_dir = 'output/corpus3/a/b/c/d/'       ## works

# [2] https://docs.python.org/3/library/os.html#os.makedirs

# Uncomment these to run "Method 1":

#directory = os.path.dirname(out_dir)
#os.makedirs(directory, mode=0o777, exist_ok=True)

# ----------------------------------------------------------------------------
# METHOD 2:
# Re-running does not overwrite existing directories and files; no errors.

# out_dir = 'output/corpus3'                ## works
# out_dir = 'output/corpus3/'               ## works
# out_dir = 'output/corpus3/doc1'           ## works
# out_dir = 'output/corpus3/doc1/'          ## works
# out_dir = 'output/corpus3/doc1/doc.txt'   ## no error but creates a .../doc.txt./ dir
# out_dir = 'output/corpus2/tfidf/'         ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/'         ## works
# out_dir = 'output/corpus3/a/b/c/d/'       ## works

# Uncomment these to run "Method 2":

#import os, errno
#try:
#       os.makedirs(out_dir)
#except OSError as e:
#       if e.errno != errno.EEXIST:
#               raise
# ----------------------------------------------------------------------------

Kesimpulan: menurut saya, "2" adalah lebih kuat.

[1] https://stackoverflow.com/questions/273192/how-can-i-create-a-directory-if-it-does-not-exist

[2] https://docs.python.org/3/library/os.html#os.makedirs

Komentar (0)

Jika anda mempertimbangkan hal berikut:

os.path.isdir('/tmp/dirname')

berarti direktori (path) ada DAN direktori. Jadi bagi saya cara ini apakah apa yang saya butuhkan. Jadi saya bisa pastikan itu adalah folder (bukan file) dan ada.

Komentar (1)