Jawaban singkat
Untuk mengecek apakah sebuah file ada, pakai os.path.isfile() dari standard library. Fungsi ini mengembalikan True kalau path itu menunjuk ke file biasa yang ada, dan False kalau tidak. Fungsi ini tidak pernah memunculkan error untuk path yang tidak ada.
Path dihitung relatif terhadap folder tempat program dijalankan (current working directory), kecuali kamu memberikan path absolut seperti /home/ada/notes.txt atau C:\Users\Ada\notes.txt.
Bagian selanjutnya di halaman ini membahas cara lain untuk menanyakan hal yang sama, apa bedanya, dan kapan sebaiknya kamu tidak menanyakannya sama sekali.
os.path.exists vs isfile vs isdir
Modul os.path punya tiga pengecekan yang mirip, dan masing-masing menjawab pertanyaan yang sedikit berbeda:
| Fungsi | Mengembalikan True kalau path itu |
|---|---|
os.path.exists(p) | apa pun yang ada: file, folder, atau symlink yang berfungsi |
os.path.isfile(p) | file biasa yang ada |
os.path.isdir(p) | folder yang ada |
Perbedaannya langsung terlihat begitu ada folder yang terlibat:
Output:
reports True False True
reports/summary.txt True True False
reports/old.txt False False False
os.path.exists("reports") bernilai True walaupun reports adalah folder. Kalau kodemu akan membaca path itu sebagai file, exists adalah pengecekan yang salah: sebuah folder akan lolos, lalu open("reports") akan gagal (dengan IsADirectoryError di Linux dan macOS, PermissionError di Windows). Pilih isfile kalau yang kamu maksud file, dan isdir kalau yang kamu maksud folder.
Dua detail lagi tentang ketiga fungsi os.path ini:
- Symlink diikuti. Link yang menunjuk ke file nyata dihitung sebagai file; link yang rusak (targetnya sudah hilang) menghasilkan
Falsedari ketiganya. - Kalau Python tidak diizinkan melihat isi sebuah folder, pengecekan mengembalikan
False, bukan memunculkanPermissionError. JadiFalseberarti "tidak ditemukan atau tidak bisa dijangkau", bukan semata "tidak ada".
Mengecek dengan pathlib
pathlib adalah API path berbasis objek di standard library, dan kebanyakan kode baru memakainya. Objek Path punya tiga pengecekan yang sama dalam bentuk method:
Path.exists(), Path.is_file() dan Path.is_dir() berperilaku seperti os.path.exists, isfile dan isdir. Operator / menggabungkan bagian-bagian path dengan pemisah yang sesuai untuk sistem operasinya, jadi folder / "summary.txt" bekerja sama baiknya di Windows, macOS, maupun Linux. Lihat penanganan file untuk membaca dan menulis lewat objek Path.
Mana yang sebaiknya kamu pakai? Kalau bagian lain kodemu sudah memakai objek Path, tetap pakai pathlib. Kalau kamu bekerja dengan string biasa dan fungsi os, os.path.isfile juga sama benarnya. Jawaban keduanya sama.
Kenapa mengecek dulu bisa jadi langkah yang salah
Alasan paling umum untuk mengecek apakah file ada adalah untuk membukanya setelah itu:
import os
if os.path.isfile("config.txt"):
with open("config.txt") as f: # the file might be gone by now
settings = f.read()
else:
settings = ""
Ada celah di sini. Di antara pemanggilan isfile() dan open(), program lain, thread lain, atau pengguna bisa menghapus atau mengganti nama file itu. Pengecekan bilang True, tapi membuka file tetap gagal, dan programmu tetap crash dengan FileNotFoundError. Celah ini disebut race condition, atau "time of check to time of use". Di laptopmu sendiri ini jarang terjadi, tapi jauh lebih sering di server sibuk tempat beberapa proses memakai folder yang sama.
Solusinya: lewati pengecekan terpisah dan biarkan open() yang menjadi pengecekannya. Python memunculkan FileNotFoundError kalau file tidak ada, dan kamu menanganinya di except:
Output:
theme=dark
(no settings file, using defaults)
Sekarang hanya ada satu operasi, bukan dua, jadi tidak ada yang bisa saling mendahului. Gaya ini punya nama di komunitas Python: EAFP, "easier to ask forgiveness than permission" (lebih mudah minta maaf daripada minta izin). Gaya sebaliknya, mengecek dulu, disebut LBYL, "look before you leap" (lihat dulu sebelum melompat). Untuk urusan file, Python cenderung memakai EAFP karena hanya sistem operasi yang tahu jawabannya tepat saat kamu membuka file.
FileNotFoundError bukan satu-satunya hal yang bisa salah. Path yang ternyata folder memunculkan IsADirectoryError (PermissionError di Windows), dan file yang tidak bisa kamu baca memunculkan PermissionError. Ketiganya adalah subclass dari OSError, jadi except OSError: menangkap semua kasus "tidak bisa dibuka" sekaligus. Halaman exception membahas cara memilih antara menangkap satu error tertentu dan menangkap satu keluarga error.
Kapan pengecekan biasa tidak masalah
Mengecek dulu tidak selalu salah. Ini alat yang tepat kalau kamu hanya butuh jawabannya dan tidak akan langsung memakai file itu di baris berikutnya:
- memilih pesan yang akan ditampilkan ("Ditemukan 3 game yang tersimpan")
- memvalidasi path yang diketik pengguna sebelum memulai pekerjaan panjang
- melewati pekerjaan yang sudah pernah dilakukan, kalau jawaban yang usang paling-paling hanya membuat pekerjaan diulang
Patokannya: kalau kamu akan membuka, membaca, menulis, atau menghapus file itu, lakukan di dalam try. Kalau kamu hanya ingin tahu, isfile() atau Path.is_file() sudah cukup.
Membuat file hanya jika belum ada
Pertanyaan kebalikannya juga sering muncul: "tulis file ini, tapi jangan pernah menimpa file yang sudah ada". Versi yang paling jelas punya race yang sama seperti tadi:
if not os.path.exists("report.txt"):
with open("report.txt", "w") as f: # another process may create it first
f.write("new report\n")
Mode "x" (exclusive creation) melakukan kedua langkah itu sekaligus. Mode ini membuat file, atau memunculkan FileExistsError kalau namanya sudah dipakai:
Output:
attempt 1: created report.txt
attempt 2: report.txt already exists, left it alone
Untuk folder, os.makedirs(path, exist_ok=True) dan Path(path).mkdir(parents=True, exist_ok=True) membuat foldernya beserta folder induk yang belum ada, dan tidak melakukan apa-apa kalau folder itu sudah ada. Tidak perlu memanggil isdir() dulu.
Kesalahan umum
- Memakai
exists()padahal yang dimaksud file. Folder dengan nama yang sama akan lolos pengecekan. Pakaiisfile()atauPath.is_file(). - Lupa dari mana path relatif dimulai.
"data.txt"dicari di current working directory, yaitu tempat kamu menjalankan program, belum tentu folder yang berisi skripnya. Untuk mencari file di sebelah skrip, bangun path-nya dariPath(__file__).parent. - Mengecek, lalu membuka. File bisa berubah di antaranya. Buka di dalam
trydan tanganiFileNotFoundError. - Menangkap semua exception.
except Exception:di sekitaropen()juga menyembunyikan salah ketik dan bug di kode yang membaca file. TangkapFileNotFoundErroratauOSError.
Pertanyaan yang sering diajukan
Bagaimana cara mengecek apakah sebuah file ada di Python?
Import os lalu panggil os.path.isfile("data.txt"), yang mengembalikan True hanya untuk file biasa yang memang ada. Dengan pathlib, caranya Path("data.txt").is_file(). Pakai os.path.exists() atau Path.exists() kalau folder dengan nama itu juga boleh dihitung.
Apa bedanya os.path.exists dan os.path.isfile?
os.path.exists(p) bernilai True untuk apa pun yang ada di path itu: file, folder, atau symlink yang menunjuk ke sesuatu yang nyata. os.path.isfile(p) bernilai True hanya untuk file biasa, jadi untuk folder hasilnya False. Pasangannya untuk folder adalah os.path.isdir(p).
Perlukah mengecek apakah file ada sebelum membukanya?
Biasanya tidak. File bisa dihapus atau dibuat di antara pengecekan dan pemanggilan open(), jadi pengecekan itu tidak menjamin apa pun. Buka file langsung di dalam try dan tangani FileNotFoundError di except. Pengecekan terpisah baru tepat kalau kamu hanya butuh jawabannya, misalnya untuk memilih pesan yang akan ditampilkan.
Bagaimana cara membuat file hanya jika file itu belum ada?
Buka dengan mode "x": open("report.txt", "x"). Python membuat file itu, atau memunculkan FileExistsError kalau sudah ada sesuatu dengan nama itu. Pengecekan dan pembuatan terjadi dalam satu langkah, jadi tidak ada program lain yang bisa menyelip di antaranya.