Perhatikan bahwa codecs.open()dalam 3.x sudah usang, karena open()mendapatkan encodingargumen.
Ignacio Vazquez-Abrams
Ada juga cara ke-3 (setidaknya dalam Python 2.x): `f = file (nama file) '
Adam Parkin
1
@ IgnacioVazquez-Abrams Apakah ada link yang codecs.open()sudah usang? Saya tidak berpikir ini di dokumen python3
varela
1
@ varela: halaman dokumentasi Python yang Anda sebutkan mengatakan: "builtin open () dan modul io terkait adalah pendekatan yang direkomendasikan untuk bekerja dengan file teks yang disandikan"
Luciano Ramalho
Jawaban:
83
Sejak Python 2.6, praktik yang baik adalah menggunakan io.open() , yang juga membutuhkan encodingargumen, seperti yang sekarang sudah usang codecs.open(). Di Python 3, io.openadalah 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 .
@ForeverWintr Jawabannya cukup jelas di sana: gunakan io.open()untuk teks, dan open()hanya untuk biner. Implikasinya adalah hal codecs.open()itu sama sekali tidak disukai.
Bdoserror
2
@Bdoserror, Ada sebuah jawaban di sana, jelas, tapi itu bukan jawaban untuk pertanyaan yang diminta. Pertanyaannya adalah tentang perbedaan antara opendan codecs.open, dan secara khusus kapan yang terakhir lebih disukai daripada yang pertama. Sebuah jawaban yang tidak terlalu disebutkan codecs.opentidak dapat menjawab pertanyaan itu.
ForeverWintr
3
@ForeverWintr Jika OP menanyakan pertanyaan yang salah (yaitu dengan asumsi yang 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".
Bdoserror
20
Secara pribadi, saya selalu menggunakan codecs.openkecuali 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.openkarena saya sangat percaya pada "eksplisit lebih baik daripada implisit" .
** - dengan Python 2.x, karena komentar pada pertanyaan yang dinyatakan dengan Python 3 openmenggantikancodecs.open
apa yang saya tidak benar-benar mengerti adalah mengapa openkadang - kadang dapat menangani dengan baik karakter non-latin yang dikodekan UTF-8 dari set unicode, dan terkadang gagal total ...
cedbeu
Ini masuk akal bagi saya. io.opentidak mengambil parameter pengkodean dari apa yang saya lihat di python 2.7.5
radtek
1
@radtek, Anda benar bahwa ini tidak berdokumen; namun (setidaknya di 2.7.12) io.openmenerima encodingdan newlineparameter dan menafsirkannya seperti yang dilakukan Python 3. Tidak seperti codecs.open, file yang dibuka dengan io.openakan memunculkan TypeError: write() argument 1 must be unicode, not strbahkan dengan Python 2.7 jika Anda mencoba untuk menulis str( bytes) padanya. File yang dibuka dengan codecs.opensebaliknya akan mencoba konversi implisit ke unicode, yang sering kali menyebabkan kebingungan UnicodeDecodeError.
jochietoch
9
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.openuntuk 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.opentidak 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.openmemungkinkan Anda melakukan yang terakhir dengan sangat mudah.
Berhati-hatilah karena Anda memberikan string unicode dan bukan bytestring yang mungkin memiliki karakter non-ASCII.
Bisakah Anda menjelaskan contoh kedua Anda? Tampaknya identik dengan contoh pertama Anda, jadi mengapa hasilnya berbeda?
Chris Johnson
Perhatikan penggunaan 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.
Mandibula79
7
Saat Anda perlu membuka file yang memiliki pengkodean tertentu, Anda akan menggunakan codecsmodul.
Saya kira semua file teks memiliki pengkodean tertentu, entah bagaimana (:
cedbeu
5
codecs.open, saya kira, hanyalah sisa dari Python 2hari - hari ketika open-in open memiliki antarmuka yang jauh lebih sederhana dan kemampuan yang lebih sedikit. Di Python 2, built-in opentidak 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.opendalam 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.xio.opensama denganbuilt-in open
catatan:
Ada perbedaan sintaksis antara codecs.opendan io.openjuga.
Tidak hanya codecs.opendan io.openberbeda dalam hal sintaks, mereka mengembalikan objek dari tipe yang berbeda. Juga codecs.openselalu bekerja dengan file dalam mode biner.
wombatonfire
4
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 openmelakukan hal yang sama seperti io.opendan dapat digunakan sebagai pengganti.
Catatan:codecs.open direncanakan untuk ditinggalkan dan diganti io.opensetelah 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 .
1. Mengapa saya tidak dapat membuka file dalam mode biner dengan io.openatau codecs.open? 2. codecs.openbelum usang, baca diskusi di halaman yang Anda tautkan.
wombatonfire
Poin bagus! 1. Anda dapat menggunakan keduanya, tetapi saya akan menyarankan sekali lagi untuk menentang codecs.open kecuali Anda menggunakan python 2.5 atau yang lebih lama. 2. Saya memperbarui jawaban saya untuk mencerminkan bahwa penghentian tidak segera terjadi, melainkan di masa mendatang.
wihlke
3
Saat Anda bekerja dengan file teks dan ingin encoding dan decoding transparan menjadi objek Unicode.
codecs.open()
dalam 3.x sudah usang, karenaopen()
mendapatkanencoding
argumen.codecs.open()
sudah usang? Saya tidak berpikir ini di dokumen python3Jawaban:
Sejak Python 2.6, praktik yang baik adalah menggunakan
io.open()
, yang juga membutuhkanencoding
argumen, seperti yang sekarang sudah usangcodecs.open()
. Di Python 3,io.open
adalah alias untuk bawaanopen()
. Jadiio.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.htmlSekarang, 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, atauopen()
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 .sumber
io.open()
untuk teks, danopen()
hanya untuk biner. Implikasinya adalah halcodecs.open()
itu sama sekali tidak disukai.open
dancodecs.open
, dan secara khusus kapan yang terakhir lebih disukai daripada yang pertama. Sebuah jawaban yang tidak terlalu disebutkancodecs.open
tidak dapat menjawab pertanyaan itu.codecs.open()
benar untuk digunakan) maka tidak ada jawaban yang "benar" tentang kapan harus menggunakannya. Jawabannya adalah dengan menggunakanio.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 digunakanopen
**. 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
sumber
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.5io.open
menerimaencoding
dannewline
parameter dan menafsirkannya seperti yang dilakukan Python 3. Tidak seperticodecs.open
, file yang dibuka denganio.open
akan memunculkanTypeError: write() argument 1 must be unicode, not str
bahkan dengan Python 2.7 jika Anda mencoba untuk menulisstr
(bytes
) padanya. File yang dibuka dengancodecs.open
sebaliknya akan mencoba konversi implisit keunicode
, yang sering kali menyebabkan kebingunganUnicodeDecodeError
.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.
sumber
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.Saat Anda perlu membuka file yang memiliki pengkodean tertentu, Anda akan menggunakan
codecs
modul.sumber
codecs.open
, saya kira, hanyalah sisa dariPython 2
hari - hari ketika open-in open memiliki antarmuka yang jauh lebih sederhana dan kemampuan yang lebih sedikit. Di Python 2, built-inopen
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 resmiNew 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 digunakanio.open
. Juga diPython 3.x
io.open
sama denganbuilt-in open
catatan:
Ada perbedaan sintaksis antara
codecs.open
danio.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)
sumber
codecs.open
danio.open
berbeda dalam hal sintaks, mereka mengembalikan objek dari tipe yang berbeda. Jugacodecs.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 sepertiio.open
dan dapat digunakan sebagai pengganti.sumber
io.open
ataucodecs.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.
sumber
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?
sumber