Saya mengalami beberapa kegagalan otak dalam memahami membaca dan menulis teks ke file (Python 2.4).
# The string, which has an a-acute in it.
ss = u'Capit\xe1n'
ss8 = ss.encode('utf8')
repr(ss), repr(ss8)
("u'Capit \ xe1n '", "' Capit \ xc3 \ xa1n '")
print ss, ss8
print >> open('f1','w'), ss8
>>> file('f1').read()
'Capit\xc3\xa1n\n'
Jadi saya mengetikkan Capit\xc3\xa1n
ke editor favorit saya, di file f2.
Kemudian:
>>> open('f1').read()
'Capit\xc3\xa1n\n'
>>> open('f2').read()
'Capit\\xc3\\xa1n\n'
>>> open('f1').read().decode('utf8')
u'Capit\xe1n\n'
>>> open('f2').read().decode('utf8')
u'Capit\\xc3\\xa1n\n'
Apa yang tidak saya mengerti di sini? Jelas ada beberapa sihir penting (atau akal sehat) yang saya lewatkan. Apa yang diketik satu dalam file teks untuk mendapatkan konversi yang tepat?
Apa yang saya benar-benar gagal grok di sini, adalah apa tujuan dari representasi UTF-8 adalah, jika Anda tidak bisa benar-benar mendapatkan Python untuk mengenalinya, ketika itu datang dari luar. Mungkin saya seharusnya hanya membuang string JSON, dan menggunakannya sebagai gantinya, karena itu memiliki representasi asciiable! Lebih penting lagi, apakah ada representasi ASCII dari objek Unicode ini yang akan dikenali dan didekode oleh Python, ketika masuk dari file? Jika demikian, bagaimana cara mendapatkannya?
>>> print simplejson.dumps(ss)
'"Capit\u00e1n"'
>>> print >> file('f3','w'), simplejson.dumps(ss)
>>> simplejson.load(open('f3'))
u'Capit\xe1n'
u'\xe1'
adalah satu titik kode UnicodeU+00e1
yang dapat direpresentasikan menggunakan 1 atau lebih byte tergantung pada pengkodean karakter (ini adalah 2 byte dalam utf-8).b'\xe1'
adalah satu byte (angka 225), huruf apa yang dapat diwakilinya tergantung pada pengkodean karakter yang digunakan untuk mendekodekannya, misalnyaб
(U+0431
) di cp1251,с
(U+0441
) di cp866, dll.Daripada mengacaukan metode encode dan decode saya merasa lebih mudah untuk menentukan encoding saat membuka file. The
io
Modul (ditambahkan dalam Python 2.6) menyediakanio.open
fungsi, yang memiliki parameter encoding.Gunakan metode terbuka dari
io
modul.Kemudian setelah memanggil fungsi read (), objek Unicode yang dikodekan dikembalikan.
Perhatikan bahwa dalam Python 3,
io.open
fungsinya adalah alias untukopen
fungsi bawaan. Fungsi terbuka bawaan hanya mendukung argumen penyandian dalam Python 3, bukan Python 2.Sunting: Sebelumnya jawaban ini merekomendasikan modul codec . The codec modul dapat menyebabkan masalah ketika pencampuran
read()
danreadline()
, jadi jawaban ini sekarang merekomendasikan io modul sebagai gantinya.Gunakan metode terbuka dari modul codec.
Kemudian setelah memanggil fungsi read (), objek Unicode yang dikodekan dikembalikan.
Jika Anda mengetahui penyandian file, menggunakan paket codec akan jauh lebih membingungkan.
Lihat http://docs.python.org/library/codecs.html#codecs.open
sumber
open(file,'w')
yangcodecs.open(file,'w','utf-8')
dipecahkancodecs.open(...)
metode ini juga sepenuhnya sesuai denganwith open(...):
gaya, di manawith
peduli tentang penutupan file setelah semua dilakukan Sepertinya tetap berhasil.with codecs.open(...) as f:
semua waktu.Sekarang yang Anda butuhkan di Python3 adalah
open(Filename, 'r', encoding='utf-8')
[Edit pada 2016-02-10 untuk klarifikasi yang diminta]
Python3 menambahkan parameter encoding ke fungsi terbuka. Informasi berikut tentang fungsi terbuka dikumpulkan dari sini: https://docs.python.org/3/library/functions.html#open
Jadi dengan menambahkan
encoding='utf-8'
sebagai parameter ke fungsi terbuka, membaca dan menulis file semuanya dilakukan sebagai utf8 (yang juga sekarang merupakan pengkodean default dari semua yang dilakukan dengan Python.)sumber
codecs.open('somefile', encoding='utf-8')
stackoverflow.com/a/147756/149428Jadi, saya telah menemukan solusi untuk apa yang saya cari, yaitu:
Ada beberapa codec yang tidak biasa yang berguna di sini. Bacaan khusus ini memungkinkan seseorang untuk mengambil representasi UTF-8 dari dalam Python, menyalinnya ke file ASCII, dan meminta mereka untuk membacanya di Unicode. Di bawah decode "string-escape", garis miring tidak akan digandakan.
Ini memungkinkan untuk semacam perjalanan pulang pergi yang saya bayangkan.
sumber
(codecs.open(file,"r","utf-8")
dan secara sederhanaopen(file,"r").read().decode("utf-8")
dan keduanya bekerja dengan sempurna.sumber
Sebenarnya, ini berhasil bagi saya untuk membaca file dengan pengkodean UTF-8 dengan Python 3.2:
sumber
Untuk membaca dalam string Unicode dan kemudian mengirim ke HTML, saya melakukan ini:
Berguna untuk server http bertenaga python.
sumber
Anda menemukan masalah penyandian secara umum: Bagaimana saya bisa tahu di mana penyandian file?
Jawab: Anda tidak bisa kecuali format file yang disediakan untuk ini. XML, misalnya, dimulai dengan:
Header ini dipilih dengan hati-hati sehingga dapat dibaca terlepas dari pengodeannya. Dalam kasus Anda, tidak ada petunjuk seperti itu, maka editor atau Python Anda tidak tahu apa yang sedang terjadi. Oleh karena itu, Anda harus menggunakan
codecs
modul dan menggunakancodecs.open(path,mode,encoding)
yang menyediakan bit yang hilang dengan Python.Adapun editor Anda, Anda harus memeriksa apakah itu menawarkan beberapa cara untuk mengatur penyandian file.
Inti dari UTF-8 adalah untuk dapat menyandikan karakter 21-bit (Unicode) sebagai aliran data 8-bit (karena itulah satu-satunya hal yang dapat ditangani oleh semua komputer di dunia). Tetapi karena sebagian besar OS mendahului era Unicode, mereka tidak memiliki alat yang sesuai untuk melampirkan informasi pengkodean ke file pada hard disk.
Masalah selanjutnya adalah representasi dalam Python. Ini dijelaskan dengan sempurna dalam komentar oleh heikogerlach . Anda harus memahami bahwa konsol Anda hanya dapat menampilkan ASCII. Untuk menampilkan Unicode atau apa pun> = charcode 128, ia harus menggunakan beberapa cara untuk melarikan diri. Di editor Anda, Anda tidak boleh mengetikkan string tampilan lolos tetapi apa artinya string (dalam hal ini, Anda harus memasukkan umlaut dan menyimpan file).
Yang mengatakan, Anda bisa menggunakan fungsi Python eval () untuk mengubah string yang lolos menjadi string:
Seperti yang Anda lihat, string "\ xc3" telah berubah menjadi satu karakter. Ini sekarang merupakan string 8-bit, disandikan UTF-8. Untuk mendapatkan Unicode:
Gregg Lind bertanya: Saya pikir ada beberapa bagian yang hilang di sini: file f2 berisi: hex:
codecs.open('f2','rb', 'utf-8')
, misalnya, membaca semuanya dalam karakter yang terpisah (diharapkan) Apakah ada cara untuk menulis ke file di ASCII yang akan berfungsi?Jawaban: Itu tergantung pada apa yang Anda maksud. ASCII tidak dapat mewakili karakter> 127. Jadi, Anda perlu cara untuk mengatakan "beberapa karakter berikutnya berarti sesuatu yang istimewa" yang dilakukan oleh urutan "\ x". Dikatakan: Dua karakter berikutnya adalah kode dari satu karakter. "\ u" melakukan hal yang sama menggunakan empat karakter untuk menyandikan Unicode hingga 0xFFFF (65535).
Jadi, Anda tidak dapat langsung menulis Unicode ke ASCII (karena ASCII tidak mengandung karakter yang sama). Anda dapat menulisnya saat string keluar (seperti pada f2); dalam hal ini, file dapat direpresentasikan sebagai ASCII. Atau Anda dapat menulisnya sebagai UTF-8, dalam hal ini, Anda memerlukan aliran aman 8-bit.
Solusi Anda menggunakan
decode('string-escape')
tidak berfungsi, tetapi Anda harus menyadari berapa banyak memori yang Anda gunakan: Tiga kali jumlah penggunaancodecs.open()
.Ingat bahwa file hanya urutan byte dengan 8 bit. Baik bit maupun byte tidak memiliki arti. Kaulah yang mengatakan "65 berarti 'A'". Karena
\xc3\xa1
harus menjadi "à" tetapi komputer tidak memiliki sarana untuk mengetahuinya, Anda harus mengetahuinya dengan menentukan pengkodean yang digunakan saat menulis file.sumber
kecuali
codecs.open()
, seseorang dapat menggunakanio.open()
untuk bekerja dengan Python2 atau Python3 untuk membaca / menulis file unicodecontoh
sumber
with io.open('data.txt', 'w', 'utf-8') as file:
dan mendapat kesalahan:TypeError: an integer is required
. Setelah saya gantiwith io.open('data.txt', 'w', encoding='utf-8') as file:
dan berhasil.Nah, editor teks favorit Anda tidak menyadari bahwa
\xc3\xa1
seharusnya karakter literal, tetapi menafsirkannya sebagai teks. Itu sebabnya Anda mendapatkan garis miring terbalik ganda di baris terakhir - sekarang garis miring terbalik +xc3
, dll. Di file Anda.Jika Anda ingin membaca dan menulis file yang disandikan dengan Python, gunakan codec terbaik modul .
Menempelkan teks antara terminal dan aplikasi sulit, karena Anda tidak tahu program mana yang akan menafsirkan teks Anda menggunakan pengkodean mana. Anda dapat mencoba yang berikut ini:
Kemudian tempelkan string ini ke editor Anda dan pastikan itu menyimpannya menggunakan Latin-1. Di bawah asumsi bahwa clipboard tidak memutarbalikkan tali, perjalanan pulang pergi akan berhasil.
sumber
Urutan \ x .. adalah sesuatu yang khusus untuk Python. Ini bukan urutan escape byte universal.
Bagaimana Anda memasukkan non-ASCII yang dikodekan UTF-8 tergantung pada OS dan / atau editor Anda. Inilah cara Anda melakukannya di Windows . Untuk OS X untuk memasuki sebuah dengan aksen akut Anda hanya dapat menekan option+ E, kemudian A, dan hampir semua teks editor di OS X dukungan UTF-8.
sumber
Anda juga dapat meningkatkan
open()
fungsi asli agar berfungsi dengan file Unicode dengan menggantinya di tempat, menggunakanpartial
fungsi tersebut. Keindahan dari solusi ini adalah Anda tidak perlu mengubah kode lama apa pun. Itu transparan.sumber
Saya mencoba mengurai iCal menggunakan Python 2.7.9:
Tapi saya mendapatkan:
dan diperbaiki hanya dengan:
(Sekarang dapat mencetak liké á böss.)
sumber
Saya menemukan pendekatan paling sederhana dengan mengubah pengkodean default seluruh skrip menjadi 'UTF-8':
apa saja
open
,print
atau pernyataan lain hanya akan digunakanutf8
.Paling tidak berfungsi untuk
Python 2.7.9
.Thx pergi ke https://markhneedham.com/blog/2015/05/21/python-unicodeencodeerror-ascii-codec-cant-encode-character-uxfc-in-position-11-ordinal-not-in-range128/ ( lihat bagian akhir).
sumber