Lebih
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?
3872
25
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 mempertimbangkanos.makedirs
untuk penciptaan.Seperti dicatat di komentar dan di tempat lain, ada's kondisi balapan – jika direktori yang dibuat antara
os.jalan.ada
danos.makedirs
panggilan,os.makedirs
akan gagal denganOSError
. Sayangnya, selimut-catchingOSError
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):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+)......dan dengan memungkinkan kata kunci argumen untuk
os.makedirs
disebutexist_ok
(3,2+).Python 3.5+:
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, loncatorang tua
argumen.Python 3.2+:
Menggunakan
pathlib
:Jika anda bisa, menginstal saat ini
pathlib
backport bernamapathlib2
. Jangan memasang lebih tua terawat backport bernamapathlib
. 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 bergunaexist_ok
pilihan. Yang backport ini dimaksudkan untuk menawarkan baru dan segala pelaksanaanmkdir
yang hilang opsi.Menggunakan
os
:os.makedirs
seperti yang digunakan di atas secara rekursif menciptakan direktori dan tidak menaikkan pengecualian jika direktori yang sudah ada. Memiliki optionalexist_ok
argumen hanya jika menggunakan Python 3.2+, dengan nilai defaultPalsu
. 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 bernamapathlib2
. Jangan memasang lebih tua terawat backport bernamapathlib
. Selanjutnya, merujuk pada Python 3.5+ bagian atas dan menggunakan hal yang sama.Menggunakan
os
:Sementara solusi naif mungkin penggunaan pertama
os.jalan.isdir
diikuti denganos.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 karenaOSError: [Errno 17] File yang ada
, yaituerrno.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.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.
Menggunakan cobalah kecuali dan kanan kode kesalahan dari errno modul menghilangkan kondisi ras dan cross-platform:
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
dibesarkanerrno.EACCES
(Izin ditolak, kesalahan 13).Saya pribadi akan merekomendasikan bahwa anda menggunakan os.jalan.isdir()
untuk menguji bukan
os.jalan.ada()`.Jika anda memiliki:
Dan bodoh input pengguna:
... Anda're akan berakhir dengan sebuah direktori bernama
nama berkas.dll
ketika anda melewati argumen itu untukos.makedirs()
jika anda menguji denganos.jalan.ada()
.Cek
os.makedirs
: (Itu membuat yakin path lengkap ada.) Untuk menangani fakta direktori mungkin ada, menangkapOSError
. (Jikaexist_ok
adalahPalsu
(default),OSError
dinaikkan jika target direktori yang sudah ada.)Mulai dari Python 3.5,
pathlib.Jalan.mkdir
memilikiexist_ok
bendera:Hal ini secara rekursif menciptakan direktori dan tidak menaikkan pengecualian jika direktori yang sudah ada.
(hanya sebagai
os.makedirs
mendapatexist_ok
bendera mulai dari python 3.2 e.gos.makedirs(jalan, exist_ok=True)
)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:
Kami ingin menghindari timpa fungsi bawaan,
dir
. Juga,path file
atau mungkinfullfilepath
mungkin adalah yang lebih baik semantik nama darifilename
jadi ini akan menjadi lebih baik ditulis: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:
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.
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: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 (ataua
untuk menambahkan). It's juga Python praktek terbaik untuk menggunakan konteks manager untuk membuka 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.Mencoba
os.jalan.ada
fungsiSaya telah menempatkan berikut turun. It's tidak benar-benar bodoh sekalipun.
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.
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:
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:
Tapi mungkin pendekatan yang lebih baik adalah dengan menghindari sumber pertikaian masalah, dengan menggunakan direktori sementara melalui
file temp
:Berikut ini's the essentials dari online doc:
Baru di Python 3.5:
pathlib.Jalan
denganexist_ok
Ada's baru
Path
objek (seperti 3.4) dengan banyak metode yang ingin digunakan dengan jalur - salah satu yangmkdir
.(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:
Kami don't harus berurusan dengan
os.jalan.bergabung sekarang - hanya bergabung dengan path bagian dengan
/`:Kemudian saya idempotently memastikan ada direktori - the
exist_ok
argumen muncul di Python 3.5:Berikut ini's bagian yang relevan dari dokumentasi:
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.
Path
benda harus dipaksa untukstr
sebelum Api lainnya yang mengharapkanstr
jalan dapat menggunakannya.Mungkin Panda harus diperbarui untuk menerima contoh abstrak kelas dasar,
os.PathLike
.Di Python 3.4 anda juga dapat menggunakan baru
pathlib
module:The relevan dokumentasi Python menunjukkan penggunaan EAFP coding style (lebih Mudah untuk Meminta Pengampunan dari Izin). Ini berarti bahwa kode
adalah lebih baik daripada alternatif
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.
Di Python3,
os.makedirs
mendukung pengaturanexist_ok
. Pengaturan default adalahFalse
, yang berartiOSError
akan dibangkitkan jika target direktori yang sudah ada. Dengan menetapkanexist_ok
keTrue
,OSError
(ada direktori) akan diabaikan dan direktori tidak akan dibuat.Di Python2,
os.makedirs
doesn't dukungan pengaturanexist_ok
. Anda dapat menggunakan pendekatan heikki-toivonen's jawaban:Anda dapat menggunakan
mkpath
Perhatikan bahwa itu akan membuat nenek moyang direktori juga.
Ia bekerja untuk Python versi 2 dan 3.
Untuk satu kapal solusinya, anda dapat menggunakan
IPython.utils.path.ensure_dir_exists()
: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.
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.
Anda dapat menggunakan
os.listdir
ini:Aku melihat Heikki Toivonen dan A-B-B's jawaban dan pemikiran dari variasi ini.
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:
Berikut ini adalah percobaan saya/catatan, yang menjelaskan hal-hal:
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
Jika anda mempertimbangkan hal berikut:
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.