Ada dua cara untuk membuka file teks dengan Python:
f = open(filename)
Dan
import codecs
f = codecs.open(filename, encoding="utf-8")
Kapan codecs.open
lebih disukai open
?
Ada dua cara untuk membuka file teks dengan Python:
f = open(filename)
Dan
import codecs
f = codecs.open(filename, encoding="utf-8")
Kapan codecs.open
lebih disukai open
?
Jawaban:
Sejak Python 2.6, praktik yang baik adalah menggunakan io.open()
, yang juga membutuhkan encoding
argumen, seperti yang sekarang sudah usang codecs.open()
. Di Python 3, io.open
adalah alias untuk bawaan open()
. Jadi io.open()
bekerja dengan Python 2.6 dan semua versi yang lebih baru, termasuk Python 3.4. Lihat dokumen: http://docs.python.org/3.4/library/io.html
Sekarang, untuk pertanyaan awal: saat membaca teks (termasuk "teks biasa", HTML, XML dan JSON) di Python 2 Anda harus selalu menggunakan io.open()
dengan pengkodean eksplisit, atau open()
dengan pengkodean eksplisit di Python 3. Melakukan itu berarti Anda mendapatkan dengan benar mendekode Unicode, atau langsung mendapatkan kesalahan, membuatnya lebih mudah untuk di-debug.
"Teks biasa" ASCII murni adalah mitos dari masa lalu. Teks bahasa Inggris yang tepat menggunakan tanda kutip keriting, tanda pisah em, peluru, € (tanda euro) dan bahkan diaeresis (¨). Jangan naif! (Dan jangan lupakan pola desain Façade!)
Karena ASCII murni bukanlah pilihan nyata, open()
tanpa pengkodean eksplisit hanya berguna untuk membaca file biner .
io.open()
untuk teks, dan open()
hanya untuk biner. Implikasinya adalah hal codecs.open()
itu sama sekali tidak disukai.
open
dan codecs.open
, dan secara khusus kapan yang terakhir lebih disukai daripada yang pertama. Sebuah jawaban yang tidak terlalu disebutkan codecs.open
tidak dapat menjawab pertanyaan itu.
codecs.open()
benar untuk digunakan) maka tidak ada jawaban yang "benar" tentang kapan harus menggunakannya. Jawabannya adalah dengan menggunakan io.open()
. Ini seperti jika saya bertanya "kapan saya harus menggunakan kunci inggris untuk menancapkan paku ke dinding?". Jawaban yang benar adalah "gunakan palu".
Secara pribadi, saya selalu menggunakan codecs.open
kecuali ada kebutuhan teridentifikasi yang jelas untuk digunakan open
**. Alasannya adalah bahwa saya sering digigit karena input utf-8 menyelinap ke dalam program saya. "Oh, saya hanya tahu itu akan selalu ascii" cenderung menjadi asumsi yang sering rusak.
Dengan asumsi 'utf-8' sebagai pengkodean default cenderung menjadi pilihan default yang lebih aman menurut pengalaman saya, karena ASCII dapat diperlakukan sebagai UTF-8, tetapi kebalikannya tidak benar. Dan dalam kasus-kasus ketika saya benar-benar tahu bahwa inputnya adalah ASCII, maka saya masih melakukan codecs.open
karena saya sangat percaya pada "eksplisit lebih baik daripada implisit" .
** - dengan Python 2.x, karena komentar pada pertanyaan yang dinyatakan dengan Python 3 open
menggantikancodecs.open
open
kadang - kadang dapat menangani dengan baik karakter non-latin yang dikodekan UTF-8 dari set unicode, dan terkadang gagal total ...
io.open
tidak mengambil parameter pengkodean dari apa yang saya lihat di python 2.7.5
io.open
menerima encoding
dan newline
parameter dan menafsirkannya seperti yang dilakukan Python 3. Tidak seperti codecs.open
, file yang dibuka dengan io.open
akan memunculkan TypeError: write() argument 1 must be unicode, not str
bahkan dengan Python 2.7 jika Anda mencoba untuk menulis str
( bytes
) padanya. File yang dibuka dengan codecs.open
sebaliknya akan mencoba konversi implisit ke unicode
, yang sering kali menyebabkan kebingungan UnicodeDecodeError
.
Di Python 2 ada string unicode dan bytestrings. Jika Anda hanya menggunakan bytestrings, Anda dapat membaca / menulis ke file yang dibuka dengan open()
baik. Bagaimanapun, string hanyalah byte.
Masalahnya muncul ketika, katakanlah, Anda memiliki string unicode dan Anda melakukan hal berikut:
>>> example = u'Μου αρέσει Ελληνικά'
>>> open('sample.txt', 'w').write(example)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
Jadi di sini jelas Anda secara eksplisit menyandikan string unicode Anda di utf-8 atau Anda gunakan codecs.open
untuk melakukannya untuk Anda secara transparan.
Jika Anda hanya pernah menggunakan bytestrings maka tidak ada masalah:
>>> example = 'Μου αρέσει Ελληνικά'
>>> open('sample.txt', 'w').write(example)
>>>
Ini menjadi lebih terlibat daripada ini karena ketika Anda menggabungkan string unicode dan bytestring dengan +
operator, Anda mendapatkan string unicode. Mudah digigit oleh yang satu itu.
Juga codecs.open
tidak suka bytestring dengan karakter non-ASCII yang diteruskan:
codecs.open('test', 'w', encoding='utf-8').write('Μου αρέσει')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/codecs.py", line 691, in write
return self.writer.write(data)
File "/usr/lib/python2.7/codecs.py", line 351, in write
data, consumed = self.encode(object, self.errors)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xce in position 0: ordinal not in range(128)
Saran tentang string untuk input / output biasanya "diubah ke unicode sedini mungkin dan kembali ke bytestring selambat mungkin". Menggunakan codecs.open
memungkinkan Anda melakukan yang terakhir dengan sangat mudah.
Berhati-hatilah karena Anda memberikan string unicode dan bukan bytestring yang mungkin memiliki karakter non-ASCII.
u''
di contoh pertama. Ini berarti saya membuat string unicode, bukan bytestring. Inilah perbedaan antara kedua contoh tersebut. Pada contoh kedua saya membuat bytestring dan menulis salah satunya ke file sudah cukup. String unicode tidak baik jika Anda menggunakan karakter di luar ASCII.
codecs.open
, saya kira, hanyalah sisa dari Python 2
hari - hari ketika open-in open memiliki antarmuka yang jauh lebih sederhana dan kemampuan yang lebih sedikit. Di Python 2, built-in open
tidak mengambil argumen encoding, jadi jika Anda ingin menggunakan sesuatu selain mode biner atau encoding default, codecs.open seharusnya digunakan.
Masuk Python 2.6
, modul io membantu untuk membuat segalanya lebih sederhana. Menurut dokumentasi resmi
New in version 2.6.
The io module provides the Python interfaces to stream handling.
Under Python 2.x, this is proposed as an alternative to the
built-in file object, but in Python 3.x it is the default
interface to access files and streams.
Karena itu, satu-satunya penggunaan yang dapat saya pikirkan codecs.open
dalam skenario saat ini adalah untuk kompatibilitas ke belakang. Dalam semua skenario lain (kecuali Anda menggunakan Python <2.6) lebih baik digunakan io.open
. Juga di Python 3.x
io.open
sama denganbuilt-in open
catatan:
Ada perbedaan sintaksis antara codecs.open
dan io.open
juga.
codecs.open
:
open(filename, mode='rb', encoding=None, errors='strict', buffering=1)
io.open
:
open(file, mode='r', buffering=-1, encoding=None,
errors=None, newline=None, closefd=True, opener=None)
codecs.open
dan io.open
berbeda dalam hal sintaks, mereka mengembalikan objek dari tipe yang berbeda. Juga codecs.open
selalu bekerja dengan file dalam mode biner.
Saat Anda ingin memuat file biner, gunakan
f = io.open(filename, 'b')
.
Untuk membuka file teks, selalu gunakan f = io.open(filename, encoding='utf-8')
dengan encoding eksplisit.
Dalam python 3 namun open
melakukan hal yang sama seperti io.open
dan dapat digunakan sebagai pengganti.
Catatan:
codecs.open
direncanakan untuk ditinggalkan dan digantiio.open
setelah diperkenalkan di python 2.6 . Saya hanya akan menggunakannya jika kode harus kompatibel dengan versi python sebelumnya. Untuk informasi lebih lanjut tentang codec dan unicode dengan python, lihat Unicode HOWTO .
io.open
atau codecs.open
? 2. codecs.open
belum usang, baca diskusi di halaman yang Anda tautkan.
Saat Anda bekerja dengan file teks dan ingin encoding dan decoding transparan menjadi objek Unicode.
Saya berada dalam situasi untuk membuka file .asm dan memproses file.
#https://docs.python.org/3/library/codecs.html#codecs.ignore_errors
#https://docs.python.org/3/library/codecs.html#codecs.Codec.encode
with codecs.open(file, encoding='cp1252', errors ='replace') as file:
Tanpa banyak masalah saya bisa membaca seluruh file, ada saran?
codecs.open()
dalam 3.x sudah usang, karenaopen()
mendapatkanencoding
argumen.