Apa cara paling elegan untuk memeriksa apakah direktori file akan ditulis ada, dan jika tidak, buat direktori menggunakan Python? Inilah 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, saya merindukan os.path.exists
(terima kasih kanja, Blair, dan Douglas). Inilah yang saya miliki sekarang:
def ensure_dir(file_path):
directory = os.path.dirname(file_path)
if not os.path.exists(directory):
os.makedirs(directory)
Apakah ada bendera untuk "terbuka", yang membuat ini terjadi secara otomatis?
os.path.mkdir
tidak ada. Inios.mkdir
.p
, berikut ini adalah cuplikan kode saya:os.makedirs(p[:p.rindex(os.path.sep)], exist_ok=True)
Jawaban:
Pada Python ≥ 3.5, gunakan
pathlib.Path.mkdir
:Untuk versi Python yang lebih lama, saya melihat dua jawaban dengan kualitas yang bagus, masing-masing dengan cacat kecil, jadi saya akan berikan pendapat saya:
Coba
os.path.exists
, dan pertimbangkanos.makedirs
untuk penciptaan.Seperti disebutkan dalam komentar dan di tempat lain, ada kondisi balapan - jika direktori dibuat antara
os.path.exists
danos.makedirs
panggilan,os.makedirs
akan gagal denganOSError
. Sayangnya, blanket-catchingOSError
dan continue tidak mudah, karena akan mengabaikan kegagalan untuk membuat direktori karena faktor lain, seperti izin yang tidak mencukupi, disk penuh, dll.Salah satu opsi adalah untuk menjebak
OSError
dan memeriksa kode kesalahan tertanam (lihat Apakah ada cara lintas platform untuk mendapatkan informasi dari OSError Python ):Atau, mungkin ada yang kedua
os.path.exists
, tapi anggap yang lain membuat direktori setelah cek pertama, lalu menghapusnya sebelum yang kedua - kita masih bisa tertipu.Tergantung pada aplikasinya, bahaya operasi bersamaan mungkin lebih atau kurang dari bahaya yang ditimbulkan oleh faktor-faktor lain seperti izin file. Pengembang harus mengetahui lebih banyak tentang aplikasi tertentu yang sedang dikembangkan dan lingkungan yang diharapkan sebelum memilih suatu implementasi.
Versi modern Python meningkatkan sedikit kode ini, baik dengan mengekspos
FileExistsError
(dalam 3.3 +) ...... dan dengan mengizinkan argumen kata kunci
os.makedirs
dipanggilexist_ok
(dalam 3.2+).sumber
os.path.exists
juga mengembalikanTrue
file. Saya telah mengirim jawaban untuk mengatasi ini.exists_ok
parameter untukos.makedirs()
dapat digunakan untuk mencakup bagaimana keberadaan sebelumnya dari jalur ditangani, karena Python 3.2.os.mkdirs()
dapat membuat folder yang tidak diinginkan jika pemisah jalur tidak sengaja ditinggalkan, folder saat ini tidak seperti yang diharapkan, elemen jalur berisi pemisah jalur. Jika Anda menggunakanos.mkdir()
bug ini akan menimbulkan pengecualian, mengingatkan Anda akan keberadaannya.Python 3.5+:
pathlib.Path.mkdir
seperti yang digunakan di atas secara rekursif membuat direktori dan tidak menimbulkan pengecualian jika direktori tersebut sudah ada. Jika Anda tidak perlu atau ingin orang tua dibuat, lewatiparents
argumen.Python 3.2+:
Menggunakan
pathlib
:Jika Anda bisa, instal
pathlib
backport saat ini bernamapathlib2
. Jangan pasang backport yang tidak terawat dengan namapathlib
. Selanjutnya, lihat bagian Python 3.5+ di atas dan gunakan yang sama.Jika menggunakan Python 3.4, meskipun sudah ada
pathlib
, ia tidak memilikiexist_ok
opsi yang berguna . Backport dimaksudkan untuk menawarkan implementasi yang lebih baru dan lebih unggulmkdir
yang mencakup opsi yang hilang ini.Menggunakan
os
:os.makedirs
seperti yang digunakan di atas secara rekursif membuat direktori dan tidak menimbulkan pengecualian jika direktori tersebut sudah ada. Ini memilikiexist_ok
argumen opsional hanya jika menggunakan Python 3.2+, dengan nilai defaultFalse
. Argumen ini tidak ada dalam Python 2.x hingga 2.7. Dengan demikian, tidak perlu penanganan pengecualian manual seperti dengan Python 2.7.Python 2.7+:
Menggunakan
pathlib
:Jika Anda bisa, instal
pathlib
backport saat ini bernamapathlib2
. Jangan pasang backport yang tidak terawat dengan namapathlib
. Selanjutnya, lihat bagian Python 3.5+ di atas dan gunakan yang sama.Menggunakan
os
:Sementara solusi naif dapat digunakan pertama kali
os.path.isdir
diikuti olehos.makedirs
, solusi di atas membalikkan urutan kedua operasi. Dengan demikian, ini mencegah kondisi ras umum yang berkaitan dengan upaya duplikasi dalam membuat direktori, dan juga memisahkan file dari direktori.Perhatikan bahwa menangkap pengecualian dan menggunakan
errno
adalah kegunaan terbatas karenaOSError: [Errno 17] File exists
, yaituerrno.EEXIST
dinaikkan untuk file dan direktori. Lebih dapat diandalkan hanya untuk memeriksa apakah direktori tersebut ada.Alternatif:
mkpath
membuat direktori bersarang, dan tidak melakukan apa pun jika direktori sudah ada. Ini berfungsi di kedua Python 2 dan 3.Per Bug 10948 , batasan parah dari alternatif ini adalah bahwa ia hanya bekerja sekali per proses python untuk jalur yang diberikan. Dengan kata lain, jika Anda menggunakannya untuk membuat direktori, lalu hapus direktori dari dalam atau di luar Python, kemudian gunakan
mkpath
lagi untuk membuat ulang direktori yang sama,mkpath
cukup diam-diam akan menggunakan informasi cache yang tidak valid karena sebelumnya telah membuat direktori, dan tidak akan sebenarnya buat direktori lagi. Sebaliknya,os.makedirs
tidak bergantung pada cache semacam itu. Batasan ini mungkin oke untuk beberapa aplikasi.Berkenaan dengan mode direktori , silakan merujuk ke dokumentasi jika Anda peduli.
sumber
os.path.isdir
orang lain menghapus folder, Anda akan menaikkan kesalahan, usang, dan membingungkan bahwa folder itu ada.Menggunakan try kecuali dan kode kesalahan yang tepat dari modul errno menghilangkan kondisi balapan dan bersifat cross-platform:
Dengan kata lain, kami mencoba membuat direktori, tetapi jika sudah ada kami mengabaikan kesalahan. Di sisi lain, setiap kesalahan lain akan dilaporkan. Misalnya, jika Anda membuat dir 'a' sebelumnya dan menghapus semua izin darinya, Anda akan mendapatkan
OSError
kenaikanerrno.EACCES
gaji (Izin ditolak, kesalahan 13).sumber
exception.errno != errno.EEXIST
tidak sengaja akan mengabaikan kasus ketika path ada tetapi merupakan objek non-direktori seperti file. Pengecualian idealnya dinaikkan jika path adalah objek non-direktori.os.makedirs(path,exist_ok=True)
exist_ok
Parameter diperkenalkan dalam Python 3.2. Itu tidak ada dalam Python 2.x. Saya akan memasukkannya ke dalam jawaban saya.Saya pribadi merekomendasikan agar Anda menggunakan
os.path.isdir()
untuk menguji daripadaos.path.exists()
.Jika Anda memiliki:
Dan input pengguna bodoh:
... Anda akan berakhir dengan direktori bernama
filename.etc
ketika Anda meneruskan argumen ituos.makedirs()
jika Anda mengujinyaos.path.exists()
.sumber
Periksa
os.makedirs
: (Memastikan path lengkap ada.)Untuk menangani fakta direktori mungkin ada, tangkap
OSError
. (Jikaexist_ok
adalahFalse
(default), sebuahOSError
dinaikkan jika direktori target sudah ada.)sumber
OSError
akan dimunculkan di sini jika path adalah file atau direktori yang ada. Saya telah mengirim jawaban untuk mengatasi ini.OSError
sebelum memutuskan untuk mengabaikannya. Lihat stackoverflow.com/a/5032238/763269 .Mulai dari Python 3.5,
pathlib.Path.mkdir
memilikiexist_ok
bendera:Ini secara rekursif membuat direktori dan tidak memunculkan pengecualian jika direktori tersebut sudah ada.
(Sama seperti
os.makedirs
mendapatexist_ok
bendera mulai dari python 3.2 misalnyaos.makedirs(path, exist_ok=True)
)sumber
Wawasan spesifik situasi ini
Anda memberikan file tertentu di jalur tertentu dan Anda menarik direktori dari jalur file. Kemudian setelah memastikan Anda memiliki direktori, Anda mencoba membuka file untuk dibaca. Untuk mengomentari kode ini:
Kami ingin menghindari menimpa fungsi builtin
dir
,. Juga,filepath
atau mungkinfullfilepath
mungkin nama semantik yang lebih baik daripadafilename
ini akan lebih baik ditulis:Tujuan akhir Anda adalah untuk membuka file ini, pada awalnya Anda menyatakan, untuk menulis, tetapi Anda pada dasarnya mendekati tujuan ini (berdasarkan kode Anda) seperti ini, yang membuka file untuk membaca :
Dengan asumsi pembukaan untuk membaca
Mengapa Anda membuat direktori untuk file yang Anda harapkan ada di sana dan dapat membaca?
Coba saja buka file.
Jika direktori atau file tidak ada, Anda akan mendapatkan
IOError
dengan nomor kesalahan terkait:errno.ENOENT
akan menunjuk ke nomor kesalahan yang benar terlepas dari platform Anda. Anda dapat menangkapnya jika mau, misalnya:Dengan asumsi kita membuka diri untuk menulis
Ini mungkin yang Anda inginkan.
Dalam hal ini, kami mungkin tidak menghadapi kondisi balapan apa pun. Jadi lakukan saja apa adanya, tetapi perhatikan bahwa untuk menulis, Anda harus membuka dengan
w
mode (ataua
menambahkan). Ini juga merupakan praktik terbaik Python untuk menggunakan manajer konteks untuk membuka file.Namun, katakanlah kami memiliki beberapa proses Python yang mencoba untuk menempatkan semua data mereka ke direktori yang sama. Maka kita mungkin memiliki pendapat tentang pembuatan direktori. Dalam hal ini yang terbaik adalah membungkus
makedirs
panggilan dalam blok coba-kecuali.sumber
Coba
os.path.exists
fungsinyasumber
os.path.mkdir()
metode. Modul os.path mengimplementasikan beberapa fungsi yang berguna pada nama path .Saya telah meletakkan berikut ini. Ini tidak sepenuhnya sangat mudah sekalipun.
Sekarang seperti yang saya katakan, ini bukan benar-benar sangat mudah, karena kami memiliki kemungkinan gagal membuat direktori, dan proses lain membuatnya selama periode itu.
sumber
os.path.exists
- lihat stackoverflow.com/a/5032238/763269, dan (2) keberhasilanos.path.exists
tidak berarti direktori itu ada, hanya jalurnya saja ada - bisa berupa file, atau symlink, atau objek sistem file lainnya.Jawaban langsung untuk ini adalah, dengan asumsi situasi sederhana di mana Anda tidak mengharapkan pengguna lain atau proses untuk mengacaukan direktori Anda:
atau jika membuat direktori tunduk pada kondisi balapan (yaitu jika setelah memeriksa jalur ada, sesuatu yang lain mungkin telah membuatnya) lakukan ini:
Tapi mungkin pendekatan yang lebih baik adalah menghindari masalah pertentangan sumber daya, dengan menggunakan direktori sementara melalui
tempfile
:Inilah hal-hal penting dari dokumen online:
Baru dalam Python 3.5:
pathlib.Path
denganexist_ok
Ada
Path
objek baru (pada 3.4) dengan banyak metode yang ingin digunakan dengan path - salah satunyamkdir
.(Untuk konteksnya, saya sedang melacak perwakilan mingguan saya dengan sebuah skrip. Inilah bagian kode yang relevan dari skrip yang memungkinkan saya menghindari memukul Stack Overflow lebih dari sekali sehari untuk data yang sama.)
Pertama impor yang relevan:
Kami tidak harus berurusan dengan
os.path.join
sekarang - cukup gabungkan bagian-bagian jalur dengan/
:Lalu saya yakin memastikan direktori itu ada -
exist_ok
argumen muncul di Python 3.5:Inilah bagian yang relevan dari dokumentasi :
Berikut ini sedikit lebih banyak skrip - dalam kasus saya, saya tidak tunduk pada kondisi balapan, saya hanya memiliki satu proses yang mengharapkan direktori (atau file yang terkandung) berada di sana, dan saya tidak memiliki apa pun yang mencoba untuk menghapus direktori.
Path
objek harus dipaksastr
sebelum API lain yang mengharapkanstr
jalur dapat menggunakannya.Mungkin Panda harus diperbarui untuk menerima contoh dari kelas dasar abstrak
os.PathLike
,.sumber
Dalam Python 3.4 Anda juga dapat menggunakan modul baru
pathlib
:sumber
pathlib
dan di manapathlib2
untuk pengguna baru, dan saya pikir pro di sini akan mencari tahu penghentian;)The dokumentasi Python relevan menyarankan penggunaan EAFP pengkodean gaya (Mudah Minta Pengampunan dari Izin) . Ini artinya kodenya
lebih baik dari pada alternatif
Dokumentasi menyarankan ini tepat karena kondisi lomba yang dibahas dalam pertanyaan ini. Selain itu, seperti yang disebutkan orang lain di sini, ada keuntungan kinerja dalam meminta sekali daripada dua kali OS. Akhirnya, argumen yang diajukan, berpotensi, mendukung kode kedua dalam beberapa kasus - ketika pengembang tahu lingkungan aplikasi sedang berjalan - hanya dapat diadvokasi dalam kasus khusus bahwa program telah menyiapkan lingkungan pribadi untuk sendiri (dan contoh lain dari program yang sama).
Bahkan dalam kasus itu, ini adalah praktik yang buruk dan dapat menyebabkan proses debug yang lama dan tidak berguna. Misalnya, fakta bahwa kami mengatur izin untuk direktori tidak boleh meninggalkan kami dengan tayangan izin diatur dengan tepat untuk tujuan kami. Direktori induk dapat dipasang dengan izin lainnya. Secara umum, suatu program harus selalu bekerja dengan benar dan programmer tidak boleh mengharapkan satu lingkungan tertentu.
sumber
Di Python3 ,
os.makedirs
mendukung pengaturanexist_ok
. Pengaturan default adalahFalse
, yang berartiOSError
akan dimunculkan jika direktori target sudah ada. Dengan mengaturexist_ok
keTrue
,OSError
(direktori ada) akan diabaikan dan direktori tidak akan dibuat.Di Python2 ,
os.makedirs
tidak mendukung pengaturanexist_ok
. Anda dapat menggunakan pendekatan ini dalam jawaban heikki-toivonen :sumber
Untuk solusi satu liner, Anda dapat menggunakan
IPython.utils.path.ensure_dir_exists()
:Dari dokumentasi : Pastikan direktori ada. Jika tidak ada, coba buat dan lindungi dari kondisi balapan jika proses lain melakukan hal yang sama.
sumber
IPython
modul benar-benar tidak dijamin untuk hadir. Ini secara asli hadir di Mac saya, tetapi tidak pada sembarang Linux saya menginstal Python. Pada dasarnya, ini bukan salah satu modul yang tercantum dalam Indeks Modul Python .pip install ipython
atau sertakan dependensi di requirement.txt atau pom.xml Anda . Dokumentasi: ipython.org/install.htmlKamu bisa menggunakan
mkpath
Perhatikan bahwa itu akan membuat direktori leluhur juga.
Ini berfungsi untuk Python 2 dan 3.
sumber
distutils.dir_util
bukan bagian dari API publik distutil dan memiliki masalah di lingkungan multi-utas: bugs.python.org/issue10948distutils.dir_util.mkpath
adalah jika Anda membuat direktori, kemudian menghapusnya dari dalam atau di luar Python, kemudian gunakanmkpath
lagi,mkpath
cukup gunakan info cache yang tidak valid karena sebelumnya telah membuat direktori, dan akan sebenarnya tidak membuat direktori lagi. Sebaliknya,os.makedirs
tidak bergantung pada cache semacam itu.Saya menggunakan
os.path.exists()
, di sini adalah skrip Python 3 yang dapat digunakan untuk memeriksa apakah direktori ada, buat satu jika tidak ada, dan hapus jika ada (jika diinginkan).Ini meminta pengguna untuk input direktori dan dapat dengan mudah dimodifikasi.
sumber
Anda dapat menggunakan
os.listdir
ini:sumber
Saya menemukan ini T / A dan saya awalnya bingung oleh beberapa kegagalan dan kesalahan yang saya dapatkan. Saya bekerja di Python 3 (v.3.5 di lingkungan virtual Anaconda pada sistem Linux x86_64 Arch).
Pertimbangkan struktur direktori ini:
Inilah eksperimen / catatan saya, yang menjelaskan berbagai hal:
Kesimpulan: menurut saya, "Metode 2" lebih kuat.
[1] Bagaimana saya bisa membuat direktori jika tidak ada?
[2] https://docs.python.org/3/library/os.html#os.makedirs
sumber
Saya melihat jawaban Heikki Toivonen dan ABB dan memikirkan variasi ini.
sumber
Gunakan cek perintah ini dan buat dir
sumber
Mengapa tidak menggunakan modul subproses jika dijalankan pada mesin yang mendukung perintah
mkdir
dengan-p
opsi? Bekerja pada python 2.7 dan python 3.6Sebaiknya lakukan trik pada kebanyakan sistem.
Dalam situasi di mana portabilitas tidak masalah (misalnya, menggunakan buruh pelabuhan) solusinya adalah 2 baris yang bersih. Anda juga tidak perlu menambahkan logika untuk memeriksa apakah direktori ada atau tidak. Akhirnya, aman untuk dijalankan kembali tanpa efek samping
Jika Anda perlu penanganan kesalahan:
sumber
Jika Anda mempertimbangkan hal berikut:
berarti direktori (jalur) ada DAN adalah direktori. Jadi bagi saya cara ini melakukan apa yang saya butuhkan. Jadi saya bisa memastikan itu folder (bukan file) dan ada.
sumber
Panggil fungsi
create_dir()
di titik masuk program / proyek Anda.sumber
Anda harus menetapkan path lengkap sebelum membuat direktori:
Ini berfungsi untuk saya dan mudah-mudahan, itu akan bekerja untuk Anda juga
sumber
Ini akan memeriksa apakah file ada di sana jika tidak maka akan membuatnya.
sumber