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?
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.
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.
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.
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.
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.
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).
Saya pribadi akan merekomendasikan bahwa anda menggunakan os.jalan.isdir()untuk menguji bukan
os.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()
.
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
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)
)
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)
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
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)
Mencoba os.jalan.ada
fungsi
if not os.path.exists(dir):
os.mkdir(dir)
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.
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.
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 sebagaiPOSIX 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
.
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.
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.
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
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.
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.
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.
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
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
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.