Apakah Anda ingin mencoba menghapus file jika ada (dan gagal jika Anda tidak memiliki izin) atau melakukan upaya terbaik menghapus dan tidak pernah memiliki kesalahan yang dilemparkan ke wajah Anda?
Donal Fellows
Saya ingin melakukan "yang pertama" dari apa yang dikatakan @DonalFellows. Untuk itu, saya kira kode asli Scott akan menjadi pendekatan yang baik?
LarsH
Buat fungsi dipanggil unlinkdan letakkan di namespace PHP.
lama12345
1
@ LarsH Lihat blok kode kedua dari jawaban yang diterima. Ini memunculkan kembali pengecualian jika pengecualian adalah kesalahan "tidak ada file atau direktori".
jpmc26
Jawaban:
613
Cara yang lebih pythonic adalah:
try:
os.remove(filename)exceptOSError:pass
Meskipun ini membutuhkan lebih banyak baris dan terlihat sangat jelek, ia menghindari panggilan yang tidak perlu os.path.exists()dan mengikuti konvensi python tentang terlalu banyak menggunakan pengecualian.
Mungkin bermanfaat untuk menulis fungsi untuk melakukan ini untuk Anda:
import os, errno
def silentremove(filename):try:
os.remove(filename)exceptOSErroras e:# this would be "except OSError, e:" before Python 2.6if e.errno != errno.ENOENT:# errno.ENOENT = no such file or directoryraise# re-raise exception if a different error occurred
Tetapi apakah ini akan lulus jika operasi penghapusan gagal (hanya baca sistem file atau masalah tak terduga lainnya)?
Scott C Wilson
136
Juga, fakta bahwa file itu ada ketika os.path.exists()dieksekusi tidak berarti bahwa itu ada ketika os.remove()dieksekusi.
Kindall
8
+1 saya, tetapi terlalu sering menggunakan pengecualian bukanlah konvensi Python :) Atau bukan?
pepr
8
@pepr Saya hanya dengan lucu mengkritik bagaimana pengecualian adalah bagian dari perilaku normal dalam python. Sebagai contoh, iterator harus menaikkan pengecualian untuk menghentikan iterasi.
Matt
5
+1 karena saya tidak bisa +2. Selain lebih Pythonic, yang ini sebenarnya benar, sedangkan yang asli tidak, karena alasan yang disarankan. Kondisi balapan seperti itu menyebabkan lubang keamanan, bug yang
sulit diperbaiki
160
Saya lebih suka menekan pengecualian daripada memeriksa keberadaan file, untuk menghindari bug TOCTTOU . Jawaban Matt adalah contoh yang bagus untuk ini, tetapi kita dapat menyederhanakannya sedikit di bawah Python 3, menggunakan contextlib.suppress():
import contextlib
with contextlib.suppress(FileNotFoundError):
os.remove(filename)
Jika filenameadalah pathlib.Pathobjek bukan string, kita dapat memanggil nya .unlink()metode daripada menggunakan os.remove(). Dalam pengalaman saya, objek Path lebih berguna daripada string untuk manipulasi sistem file.
Karena segala sesuatu dalam jawaban ini eksklusif untuk Python 3, itu memberikan alasan lain untuk memutakhirkan.
Ini adalah cara yang paling pythonic pada Desember 2015. Python terus berevolusi.
Mayank Jaiswal
2
Saya tidak menemukan metode remove () untuk objek pathlib.Path di Python 3.6
BrianHVB
1
@jeffbyrnes: Saya menyebutnya pelanggaran Zen Python: "Seharusnya ada satu - dan lebih baik hanya satu - cara yang jelas untuk melakukannya." Jika Anda memiliki dua metode yang melakukan hal yang sama, Anda akan berakhir dengan campuran mereka dalam menjalankan kode sumber, yang akan lebih sulit bagi pembaca untuk mengikuti. Saya curiga mereka menginginkan konsistensi unlink(2), yang sejauh ini merupakan antarmuka relevan tertua di sini.
Kevin
1
@nivk: Jika Anda memerlukan exceptklausa, maka Anda harus menggunakan try/ except. Hal ini tidak dapat bermakna dipersingkat, karena Anda harus memiliki garis untuk memperkenalkan blok pertama, blok itu sendiri, garis untuk memperkenalkan blok kedua, dan kemudian blok, sehingga try/ exceptsudah sebagai singkat mungkin.
Kevin
1
Layak ditunjukkan bahwa tidak seperti blok coba / kecuali, solusi ini berarti Anda tidak perlu dipusingkan membuat pengecualian untuk memastikan bahwa metrik cakupan pengujian relevan.
thclark
50
os.path.existskembali Trueuntuk folder dan juga file. Coba gunakan os.path.isfileuntuk memeriksa apakah file itu ada.
Setiap kali kami menguji keberadaan dan kemudian menghapus berdasarkan tes itu, kami membuka diri untuk kondisi balapan. (Bagaimana jika file tersebut menghilang di antara?)
Alex L
34
Dalam semangat jawaban Andy Jones, bagaimana dengan operasi ternary yang otentik:
@BrianHVB Karena ada terner untuk memilih antara dua nilai berdasarkan suatu kondisi, bukan untuk melakukan percabangan.
bgusach
1
Saya tidak suka menggunakan pengecualian untuk kontrol aliran. Mereka membuat kode sulit dipahami dan yang lebih penting dapat menutupi beberapa kesalahan lain yang terjadi (seperti masalah izin memblokir penghapusan file) yang akan menyebabkan kegagalan diam.
Ed King
11
Ini bukan atom. File dapat dihapus antara panggilan yang ada dan yang dihapus. Lebih aman untuk mencoba operasi dan membiarkannya gagal.
ConnorWGarvey
1
@ nam-g-vu Hanya FYI, saya memutar kembali hasil edit Anda karena pada dasarnya Anda hanya menambahkan sintaks si penanya asli sebagai alternatif. Karena mereka mencari sesuatu yang berbeda dari itu, saya tidak merasa bahwa pengeditan cocok dengan jawaban khusus ini.
Tim Keating
10
Pada Python 3.8, gunakan missing_ok=Truedan pathlib.Path.unlink( dokumentasi di sini )
from pathlib importPath
my_file =Path("./dir1/dir2/file.txt")# Python 3.8+
my_file.unlink(missing_ok=True)# Python 3.7 and earlierif my_file.exists():
my_file.unlink()
Banyak dari Anda mungkin tidak setuju - mungkin karena alasan seperti mempertimbangkan usulan penggunaan terner "jelek" - tetapi ini menimbulkan pertanyaan apakah kita harus mendengarkan orang-orang yang terbiasa dengan standar jelek ketika mereka menyebut sesuatu yang tidak standar "jelek".
ini bersih - saya tidak suka menggunakan pengecualian untuk kontrol aliran. Mereka membuat kode sulit dipahami dan yang lebih penting dapat menutupi beberapa kesalahan lain yang terjadi (seperti masalah izin memblokir penghapusan file) yang akan menyebabkan kegagalan diam.
Ed King
2
Itu tidak cantik karena mengasumsikan hanya ada satu proses yang akan mengubah nama file. Itu bukan atom. Aman dan benar untuk mencoba operasi dan gagal dengan anggun. Sangat menyebalkan bahwa Python tidak dapat melakukan standarisasi. Jika kami memiliki direktori, kami akan menggunakan shutil dan itu akan mendukung apa yang kami inginkan.
ConnorWGarvey
2
Dalam versi Python 3.4 atau yang lebih baru, cara pythonic adalah:
import os
from contextlib import suppress
with suppress(OSError):
os.remove(filename)
Sesuatu seperti ini? Mengambil keuntungan dari evaluasi hubung singkat. Jika file tidak ada, seluruh persyaratan tidak mungkin benar, sehingga python tidak akan repot mengevaluasi bagian kedua.
Ini jelas bukan "lebih Pythonic" —bahkan, itu adalah sesuatu yang secara spesifik diperingatkan Guido, dan disebut sebagai "penyalahgunaan" dari operator boolean.
abarnert
1
oh, saya setuju - bagian dari pertanyaan yang diajukan untuk satu jalur dan ini adalah hal pertama yang muncul di kepala saya
Andy Jones
4
Nah, Anda juga bisa menjadikannya one-liner dengan hanya menghapus baris baru setelah titik dua ... Atau, lebih baik lagi, Guide dengan enggan menambahkan ekspresi jika untuk menghentikan orang dari "menyalahgunakan operator boolean", dan ada peluang besar untuk membuktikan bahwa apa pun dapat disalahgunakan: os.remove ("gogogo.php") jika os.path.exists ("gogogo.php") yang lain Tidak ada. :)
Jika Anda harus menulis seluruh fungsi itu agak merindukan titik satu-liners
Ion Lesan
@Ion Lesan OP mencari cara "terbaik" untuk menyelesaikan masalah ini. Satu liner tidak pernah menjadi cara yang lebih baik jika membahayakan keterbacaan.
Baz
Dengan definisi "terbaik" yang pada dasarnya luas, saya tidak akan berdebat dalam pengertian ini, meskipun jelas dipengaruhi oleh TOCTOU. Dan jelas bukan solusi CIUMAN.
Ion Lesan
@ Matt Benar tetapi tidakkah sejumlah solusi yang ditawarkan di sini menderita masalah ini?
Baz
0
Ini adalah solusi lain:
if os.path.isfile(os.path.join(path, filename)):
os.remove(os.path.join(path, filename))
Saya telah menggunakan rmyang dapat memaksa untuk menghapus file yang tidak ada dengan --preserve-rootsebagai opsi untuk rm.
--preserve-root
donot remove `/' (default)
rm --help | grep "force"-f,--force ignore nonexistent files and arguments, never prompt
Kita juga bisa menggunakan safe-rm ( sudo apt-get install safe-rm)
Safe-rm adalah alat keamanan yang dimaksudkan untuk mencegah penghapusan file penting secara tidak disengaja dengan mengganti / bin / rm dengan pembungkus, yang memeriksa argumen yang diberikan terhadap daftar hitam file dan direktori yang dapat dikonfigurasi yang tidak boleh dihapus.
Pertama saya memeriksa apakah folder / path file ada atau tidak. Ini akan mencegah pengaturan variabel fileToRemove /folderToRemove to the string-r / `.
Menggunakan shell untuk sesuatu yang sepele ini berlebihan dan pendekatan ini juga tidak akan bekerja lintas platform (mis. Windows).
Nabla
4
Menggunakan shell alih-alih library standar (os.remove misalnya) selalu merupakan salah satu cara yang paling tidak pythonic / bersih dalam melakukan sesuatu. Misalnya Anda harus secara manual menangani kesalahan yang dikembalikan oleh shell.
Nabla
1
Saya menambahkan jawaban saya untuk digunakan rmdengan aman dan mencegah rm -r /. @JonBrave
alper
1
rm -f --preserve-roottidak cukup baik ( --preserve-rootmungkin standarnya sih). Saya memberi -r /contoh , bagaimana jika itu -r /homeatau apa pun? Anda mungkin ingin rm -f -- $fileToRemove, tetapi bukan itu intinya.
JonBrave
3
Bukan cara Anda menggunakannya, dengan nama variabel (variabel lingkungan), dan tanpa kutip, dan tanpa perlindungan, tidak. Dan bukan untuk pertanyaan ini, tidak. Mengekspos yang tidak waspada os.system('rm ...')sangat berbahaya, maaf.
unlink
dan letakkan di namespace PHP.Jawaban:
Cara yang lebih pythonic adalah:
Meskipun ini membutuhkan lebih banyak baris dan terlihat sangat jelek, ia menghindari panggilan yang tidak perlu
os.path.exists()
dan mengikuti konvensi python tentang terlalu banyak menggunakan pengecualian.Mungkin bermanfaat untuk menulis fungsi untuk melakukan ini untuk Anda:
sumber
os.path.exists()
dieksekusi tidak berarti bahwa itu ada ketikaos.remove()
dieksekusi.Saya lebih suka menekan pengecualian daripada memeriksa keberadaan file, untuk menghindari bug TOCTTOU . Jawaban Matt adalah contoh yang bagus untuk ini, tetapi kita dapat menyederhanakannya sedikit di bawah Python 3, menggunakan
contextlib.suppress()
:Jika
filename
adalahpathlib.Path
objek bukan string, kita dapat memanggil nya.unlink()
metode daripada menggunakanos.remove()
. Dalam pengalaman saya, objek Path lebih berguna daripada string untuk manipulasi sistem file.Karena segala sesuatu dalam jawaban ini eksklusif untuk Python 3, itu memberikan alasan lain untuk memutakhirkan.
sumber
unlink(2)
, yang sejauh ini merupakan antarmuka relevan tertua di sini.except
klausa, maka Anda harus menggunakantry
/except
. Hal ini tidak dapat bermakna dipersingkat, karena Anda harus memiliki garis untuk memperkenalkan blok pertama, blok itu sendiri, garis untuk memperkenalkan blok kedua, dan kemudian blok, sehinggatry
/except
sudah sebagai singkat mungkin.os.path.exists
kembaliTrue
untuk folder dan juga file. Coba gunakanos.path.isfile
untuk memeriksa apakah file itu ada.sumber
Dalam semangat jawaban Andy Jones, bagaimana dengan operasi ternary yang otentik:
sumber
Pada Python 3.8, gunakan
missing_ok=True
danpathlib.Path.unlink
( dokumentasi di sini )sumber
Cara lain untuk mengetahui apakah file (atau file) ada, dan untuk menghapusnya, menggunakan modul glob.
Glob menemukan semua file yang dapat memilih pola dengan wildcard * nix, dan mengulang daftar.
sumber
Jawaban Matt adalah jawaban yang tepat untuk Python yang lebih lama dan Kevin jawaban yang tepat untuk yang lebih baru.
Jika anda tidak ingin menyalin fungsi untuk
silentremove
, fungsi ini terkena di path.py sebagai remove_p :sumber
adalah satu-liner.
Banyak dari Anda mungkin tidak setuju - mungkin karena alasan seperti mempertimbangkan usulan penggunaan terner "jelek" - tetapi ini menimbulkan pertanyaan apakah kita harus mendengarkan orang-orang yang terbiasa dengan standar jelek ketika mereka menyebut sesuatu yang tidak standar "jelek".
sumber
Dalam versi Python 3.4 atau yang lebih baru, cara pythonic adalah:
sumber
Sesuatu seperti ini? Mengambil keuntungan dari evaluasi hubung singkat. Jika file tidak ada, seluruh persyaratan tidak mungkin benar, sehingga python tidak akan repot mengevaluasi bagian kedua.
sumber
Penawaran KISS:
Lalu:
sumber
Ini adalah solusi lain:
sumber
Solusi lain dengan pesan Anda sendiri dalam pengecualian.
sumber
Saya telah menggunakan
rm
yang dapat memaksa untuk menghapus file yang tidak ada dengan--preserve-root
sebagai opsi untukrm
.Kita juga bisa menggunakan safe-rm (
sudo apt-get install safe-rm
)Pertama saya memeriksa apakah folder / path file ada atau tidak. Ini akan mencegah pengaturan variabel fileToRemove
/
folderToRemoveto the string
-r / `.sumber
rm
dengan aman dan mencegahrm -r /
. @JonBraverm -f --preserve-root
tidak cukup baik (--preserve-root
mungkin standarnya sih). Saya memberi-r /
contoh , bagaimana jika itu-r /home
atau apa pun? Anda mungkin inginrm -f -- $fileToRemove
, tetapi bukan itu intinya.os.system('rm ...')
sangat berbahaya, maaf.