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.open
tercih 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.open
tercih 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 encoding
argüman da alan iyi bir uygulama kullanmaktır codecs.open()
. Python 3'te, yerleşik io.open
iç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.
open
ve codecs.open
ikincisi, birincisine tercih olduğunda spesifik olarak ve. Bahsetmek kadar fazla codecs.open
olmayan 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.open
kullanı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 open
aldığındancodecs.open
open
bazen 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.open
python
io.open
kabul eder encoding
, newline
parametreler ve bunları Python 3'ün yaptığı gibi yorumlar. Aksine codecs.open
, ( ) yazmayı denerseniz, Python 2.7'de bile açılmış bir dosya io.open
yü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 str
str
bytes
codecs.open
unicode
UnicodeDecodeError
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.open
sizin 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.open
ASCII 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 2
yerleş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 open
kodlama 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.open
sonra, 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.open
ve io.open
söz dizimi bakımından farklılık, farklı türdeki nesneleri döndürür. Ayrıca codecs.open
her 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 open
aynı şeyi yapar io.open
ve bunun yerine kullanılabilir.
Not: kullanımdan kaldırılması ve python 2.6'da kullanıma sunulmasından sonra yerini alması
codecs.open
planlanmaktadı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.open
veya ile açamıyorum codecs.open
? 2. codecs.open
henü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