Python'da bir metin dosyası açmanın iki yolu vardır:
f = open(filename)
Ve
import codecs
f = codecs.open(filename, encoding="utf-8")
Ne zaman codecs.opentercih edilir open?
Python'da bir metin dosyası açmanın iki yolu vardır:
f = open(filename)
Ve
import codecs
f = codecs.open(filename, encoding="utf-8")
Ne zaman codecs.opentercih edilir open?
codecs.open()mı? Bunu python3 belgelerinde düşünmüyorum: docs.python.org/3.7/library/codecs.html
Yanıtlar:
Python 2.6'dan beri , artık kullanılmayan gibi io.open()bir encodingargüman da alan iyi bir uygulama kullanmaktır codecs.open(). Python 3'te, yerleşik io.openiçin bir takma addır open(). Yani io.open()Python 2.6 ve Python 3.4 dahil tüm sonraki sürümlerinde çalışır. Dokümanlara bakın: http://docs.python.org/3.4/library/io.html
Şimdi, orijinal soru için: okurken metni size gereken Python 2'de (HTML, XML ve JSON "düz metin" dahil) her zaman kullanmak io.open()açık bir kodlamayla veya open()Python 3'te açık bir kodlamayla Aksi araçlarının doğru olsun Unicode'un kodunu çözebilir veya hemen bir hata alarak, hata ayıklamayı çok daha kolay hale getirir.
Saf ASCII "düz metin" uzak geçmişten bir efsanedir. Uygun İngilizce metinler kıvrık tırnak işaretleri, uzun tireler, madde işaretleri, € (euro işaretleri) ve hatta iki nokta (¨) kullanır. Saf olmayın! (Ve Cephe tasarım modelini de unutmayalım!)
Saf ASCII gerçek bir seçenek open()olmadığından, açık bir kodlama olmadan yalnızca ikili dosyaları okumak için kullanışlıdır .
io.open()metin için ve open()sadece ikili için kullanın. Bunun anlamı, codecs.open()hiç tercih edilmemesidir.
openve codecs.openikincisi, birincisine tercih olduğunda spesifik olarak ve. Bahsetmek kadar fazla codecs.openolmayan bir cevap bu soruyu cevaplayamaz.
codecs.open()kullanımın doğru olduğu varsayımıyla ) o zaman ne zaman kullanılacağına dair "doğru" bir cevap yoktur. Cevap io.open()bunun yerine kullanmaktır . Sanki "duvara çivi çakmak için ne zaman anahtar kullanmalıyım?" Doğru cevap "çekiç kullan" dır.
Şahsen ben her zaman kullanmak codecs.openkullanımına açık tanımlanmış bir ihtiyaç yoksa open**. Bunun nedeni, programlarıma utf-8 girdisini gizlice sokarak ısırıldığım birçok kez oldu. "Ah, bunun her zaman ascii olacağını biliyorum" sık sık bozulan bir varsayım olma eğilimindedir.
Varsayılan kodlama olarak 'utf-8'i varsaymak, deneyimlerime göre daha güvenli bir varsayılan seçimdir, çünkü ASCII UTF-8 olarak değerlendirilebilir, ancak tersi doğru değildir. Ve bu durumlarda , girdinin ASCII olduğunu gerçekten bildiğimde , o zaman hala "açık, örtükten daha iyidir"codecs.open inancına sahip olduğum gibi yapıyorum .
** - Python 2.x'te, soruya yapılan yorum Python 3'te yer openaldığındancodecs.open
openbazen unicode setinin UTF-8 kodlu latin olmayan karakterlerini çok iyi işleyebildiği ve bazen başarısız bir şekilde başarısız olduğu ...
io.openpython
io.openkabul eder encoding, newlineparametreler ve bunları Python 3'ün yaptığı gibi yorumlar. Aksine codecs.open, ( ) yazmayı denerseniz, Python 2.7'de bile açılmış bir dosya io.openyükselecektir . İle açılan bir dosya , bunun yerine örtük dönüştürmeyi deneyecek ve genellikle kafa karıştırıcı e -postalara neden olacaktır . TypeError: write() argument 1 must be unicode, not strstrbytescodecs.openunicodeUnicodeDecodeError
Python 2'de unicode dizeleri ve bytestrings vardır. Sadece bytestrings kullanırsanız, açılmış bir dosyayı open()gayet iyi okuyabilir / yazabilirsiniz . Sonuçta, dizeler yalnızca bayttır.
Sorun, örneğin bir unicode dizeniz olduğunda ve aşağıdakileri yaptığınızda ortaya çıkar:
>>> 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)
Yani burada açıkçası, unicode dizenizi utf-8'de açıkça kodluyorsunuz veya bunu codecs.opensizin için şeffaf bir şekilde yapmak için kullanıyorsunuz .
Yalnızca bytestrings kullanıyorsanız, sorun yok:
>>> example = 'Μου αρέσει Ελληνικά'
>>> open('sample.txt', 'w').write(example)
>>>
Bundan daha fazla işin içine girer, çünkü bir unicode ve +operatörle bytestring dizgesini birleştirdiğinizde, bir unicode dizesi elde edersiniz. Onun tarafından ısırılması kolay.
Ayrıca codecs.openASCII olmayan karakterlerin geçtiği bytestrings'i sevmez:
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)
Girdi / çıktı dizgeleri hakkında tavsiye, normalde "mümkün olduğu kadar erken unicode'a ve mümkün olduğu kadar geç bytestrings'e dönme" şeklindedir. Kullanmak codecs.open, ikincisini çok kolay bir şekilde yapmanızı sağlar.
Unicode dizeleri verdiğinize dikkat edin, ASCII olmayan karakterlere sahip olabilecek testlere değil.
u''İlk örnekteki kullanımına dikkat edin . Bu, bytestring değil, bir unicode dizesi oluşturduğum anlamına geliyor. Bu, iki örnek arasındaki farktır. İkinci örnekte bir bytestring oluşturuyorum ve bunlardan birini bir dosyaya yazmak gayet iyi. ASCII dışında karakterler kullanıyorsanız, bir unicode dizesi uygun değildir.
codecs.open, sanırım, Python 2yerleşik açıklığın çok daha basit bir arayüze ve daha az yeteneğe sahip olduğu günlerden kalan bir şey. Python 2'de yerleşik openkodlama argümanı almaz, bu nedenle ikili mod veya varsayılan kodlamadan başka bir şey kullanmak isterseniz codecs.open kullanılması gerekiyordu.
İçinde Python 2.6 , io modülü işleri biraz daha basit hale getirmek için yardıma geldi. Resmi belgelere göre
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.
Bunu söyledikten codecs.opensonra, mevcut senaryoda düşünebildiğim tek kullanım geriye dönük uyumluluk. Diğer tüm senaryolarda (Python <2.6 kullanmıyorsanız) kullanılması tercih edilir io.open. AyrıcaPython 3.x io.open aynıdırbuilt-in open
Not:
Arasında sözdizimsel bir fark var codecs.open veio.open .
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.openve io.opensöz dizimi bakımından farklılık, farklı türdeki nesneleri döndürür. Ayrıca codecs.openher zaman ikili moddaki dosyalarla çalışır.
İkili dosya yüklemek istediğinizde
f = io.open(filename, 'b').
Bir metin dosyasını açmak için her zaman f = io.open(filename, encoding='utf-8')açık kodlamayla kullanın .
Gelen piton 3 Ancak openaynı şeyi yapar io.openve bunun yerine kullanılabilir.
Not: kullanımdan kaldırılması ve python 2.6'da kullanıma sunulmasından sonra yerini alması
codecs.openplanlanmaktadır . Bunu yalnızca kodun önceki python sürümleriyle uyumlu olması gerekiyorsa kullanırdım. Python'da kodekler ve unicode hakkında daha fazla bilgi için Unicode NASIL belgesine bakın .io.open
io.openveya ile açamıyorum codecs.open? 2. codecs.openhenüz kullanımdan kaldırılmadı, bağlantı verdiğiniz sayfadaki tartışmayı okuyun.
Metin dosyalarıyla çalışırken ve şeffaf kodlama ve Unicode nesnelerine kod çözme istediğinizde.
Bir .asm dosyasını açıp dosyayı işleme koyacak bir durumdaydım.
#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:
Çok fazla sorun yaşamadan tüm dosyayı okuyabilirim, herhangi bir öneri?
codecs.open(), bunun 3.x'te kullanılmadığına dikkat edin .open()encoding