Jawaban:
Jawaban atas pertanyaan itu agak tergantung pada implementasi Python tertentu.
Untuk memahami semua ini, berikan perhatian khusus pada file
objek yang sebenarnya . Dalam kode Anda, objek itu disebutkan hanya sekali, dalam ekspresi, dan menjadi tidak dapat diakses segera setelah read()
panggilan kembali.
Ini berarti bahwa objek file adalah sampah. Satu-satunya pertanyaan yang tersisa adalah "Kapan pemungut sampah mengumpulkan objek file?".
dalam CPython, yang menggunakan penghitung referensi, jenis sampah ini langsung diperhatikan, dan karenanya akan segera dikumpulkan. Ini biasanya tidak berlaku untuk implementasi python lainnya.
Solusi yang lebih baik, untuk memastikan bahwa file ditutup, adalah pola ini:
with open('Path/to/file', 'r') as content_file:
content = content_file.read()
yang akan selalu menutup file segera setelah blok berakhir; bahkan jika pengecualian terjadi.
Sunting: Untuk memberikan poin yang lebih baik:
Selain file.__exit__()
, yang "secara otomatis" dipanggil dalam with
pengaturan manajer konteks, satu-satunya cara lain yang file.close()
secara otomatis dipanggil (yaitu, selain secara eksplisit menyebutnya sendiri,) adalah melalui file.__del__()
. Ini membawa kita pada pertanyaan kapan __del__()
dipanggil?
Program yang ditulis dengan benar tidak dapat mengasumsikan bahwa finalis akan pernah berjalan pada titik mana pun sebelum penghentian program.
- https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203
Khususnya:
Objek tidak pernah secara eksplisit dihancurkan; Namun, ketika mereka menjadi tidak terjangkau mereka mungkin menjadi sampah. Suatu implementasi diperbolehkan untuk menunda pengumpulan sampah atau menghilangkannya sama sekali - ini adalah masalah kualitas implementasi bagaimana pengumpulan sampah dilaksanakan, selama tidak ada benda yang dikumpulkan yang masih dapat dijangkau.
[...]
CPython saat ini menggunakan skema penghitungan referensi dengan deteksi (opsional) yang tertunda terhadap sampah yang terhubung secara siklikal, yang mengumpulkan sebagian besar objek segera setelah mereka menjadi tidak terjangkau, tetapi tidak dijamin untuk mengumpulkan sampah yang mengandung referensi melingkar.
- https://docs.python.org/3.5/reference/datamodel.html#objects-values-and-types
(Penekanan milikku)
tetapi seperti yang disarankan, implementasi lain mungkin memiliki perilaku lain. Sebagai contoh, PyPy memiliki 6 implementasi pengumpulan sampah yang berbeda !
__exit__()
dalam kasus seperti itu terdengar seperti cacat desain.
try
/ finally
menjadi fiddly dan sangat berguna bagi petugas kebersihan yang with
memecahkan masalah. Perbedaan antara "menutup secara eksplisit" dan "mengelola dengan with
" adalah bahwa penangan keluar dipanggil meskipun ada pengecualian. Anda bisa memasukkannya ke close()
dalam finally
klausa, tetapi itu tidak jauh berbeda dengan menggunakan with
, sedikit lebih berantakan (3 baris tambahan, bukan 1), dan sedikit lebih sulit untuk membuatnya dengan benar.
with foo() as f: [...]
pada dasarnya adalah sama f = foo()
, f.__enter__()
, [...] dan f.__exit__()
dengan pengecualian ditangani , sehingga __exit__
selalu disebut. Jadi file selalu ditutup.
Anda dapat menggunakan pathlib .
Untuk Python 3.5 dan lebih tinggi:
from pathlib import Path
contents = Path(file_path).read_text()
Untuk versi Python yang lebih lama, gunakan pathlib2 :
$ pip install pathlib2
Kemudian:
from pathlib2 import Path
contents = Path(file_path).read_text()
Ini adalah read_text
implementasi aktual :
def read_text(self, encoding=None, errors=None):
"""
Open the file in text mode, read it, and close the file.
"""
with self.open(mode='r', encoding=encoding, errors=errors) as f:
return f.read()
Nah, jika Anda harus membaca file baris demi baris agar bisa bekerja dengan setiap baris, Anda bisa menggunakannya
with open('Path/to/file', 'r') as f:
s = f.readline()
while s:
# do whatever you want to
s = f.readline()
Atau bahkan cara yang lebih baik:
with open('Path/to/file') as f:
for line in f:
# do whatever you want to
Alih-alih mengambil konten file sebagai string tunggal, mungkin berguna untuk menyimpan konten sebagai daftar semua baris yang terdiri dari file :
with open('Path/to/file', 'r') as content_file:
content_list = content_file.read().strip().split("\n")
Seperti yang bisa dilihat, kita perlu menambahkan metode gabungan .strip().split("\n")
ke jawaban utama di utas ini .
Di sini, .strip()
cukup hapus spasi putih dan karakter baris baru di akhir seluruh string file, dan .split("\n")
buat daftar aktual melalui pemisahan seluruh string file di setiap karakter baris baru \ n .
Selain itu, dengan cara ini seluruh konten file dapat disimpan dalam variabel, yang mungkin diinginkan dalam beberapa kasus, alih-alih mengulangi file baris demi baris seperti yang ditunjukkan dalam jawaban sebelumnya .