Python'da dosyadan karakter okuma


102

Bir metin dosyasında "Bundan hoşlanmadım" dizesi vardır.

Ancak, onu bir dizge halinde okuduğumda, "Böyle bir \ xe2 \ x80 \ x98t yapmıyorum" oluyor. "" "İfadesinin unicode temsili olduğunu anlıyorum. kullanırım

f1 = open (file1, "r")
text = f1.read()

okuma yapmak için komut.

Şimdi, dizgeyi, dizgeye okunduğunda, "Bunu sevmiyorum" yerine "Bundan hoşlanmadım" şeklinde okumak mümkün mü?

İkinci düzenleme: Bazı kişilerin bu sorunu çözmek için haritalama kullandığını gördüm, ancak gerçekten, bu tür ANSI'yi unicode'a (ve tersi) dönüştüren yerleşik bir dönüştürme yok mu?


Bazı yorumlar: Bazı kişilerin bu sorunu çözmek için haritalama kullandığını gördüm, ancak gerçekten, bu tür ANSI'yi unicode'a (ve tersi) dönüştüren yerleşik bir dönüştürme yok mu? Teşekkürler!
Graviton

Yok, çünkü yüz binlerce Unicode kod noktası var. Hangisinin hangi ASCII karakterleriyle eşleştirilmesi gerektiğine nasıl karar verirsiniz?
John Millikin

2
btw, metin dosyanız bozuldu! U + 2018, kesme işareti değil, "SOL TEK TEK TEKLİF İŞARETİ" dir (en yaygın olarak U + 0027).

John, yorumun yanlış, en azından genel anlamda. iconv lib, unicode karakterleri ascii'ye çevirmek için kullanılabilir (hatta yerel ayara bağlı. $ python -c 'print u "\ u2018" .encode ("utf-8")' | iconv -t 'ascii // translit' | xxd 0000000: 270a

mesele şu ki, UNICODE'u ASCII'ye dönüştürmeniz gerekir (tam tersi değil).
hasen

Yanıtlar:


158

Referans: http://docs.python.org/howto/unicode

Unicode'u bir dosyadan okumak bu nedenle basittir:

import codecs
with codecs.open('unicode.rst', encoding='utf-8') as f:
    for line in f:
        print repr(line)

Dosyaları güncelleme modunda açarak hem okumaya hem de yazmaya izin vermek de mümkündür:

with codecs.open('test', encoding='utf-8', mode='w+') as f:
    f.write(u'\u4500 blah blah blah\n')
    f.seek(0)
    print repr(f.readline()[:1])

DÜZENLEME : Amaçladığınız hedefin dosyayı Python'da bir dizeye doğru bir şekilde okuyabilmek olduğunu varsayıyorum. Unicode'dan bir ASCII dizesine dönüştürmeye çalışıyorsanız, bunu yapmanın doğrudan bir yolu yoktur, çünkü Unicode karakterleri ASCII'de mutlaka bulunmayacaktır.

Bir ASCII dizesine dönüştürmeye çalışıyorsanız, aşağıdakilerden birini deneyin:

  1. Bu özel örnek gibi yalnızca birkaç özel durumu ele almak istiyorsanız, belirli unicode karakterlerini ASCII eşdeğerleriyle değiştirin

  2. Mümkün olan unicodedataen iyi şekilde bir sonraki ASCII eşdeğerine dönüştürmek için modülün normalize()ve string.encode()yöntemini kullanın (Ref https://web.archive.org/web/20090228203858/http://techxplorer.com/2006/07/18/converting- unicode-ascii-kullanarak-python ):

    >>> teststr
    u'I don\xe2\x80\x98t like this'
    >>> unicodedata.normalize('NFKD', teststr).encode('ascii', 'ignore')
    'I donat like this'

3
codecsmodülü evrensel satırsonu modunu düzgün şekilde işlemez. io.open()Bunun yerine Python 2.7+ üzerinde kullanın ( open()Python 3 üzerinde yerleşiktir ).
jfs

15

Dikkate alınması gereken birkaç nokta var.

Bir \ u2018 karakteri yalnızca Python'daki bir unicode dizesinin temsilinin bir parçası olarak görünebilir, örneğin:

>>> text = u'‘'
>>> print repr(text)
u'\u2018'

Şimdi sadece unicode dizesini güzelce yazdırmak istiyorsanız, sadece unicode encodeyöntemini kullanın :

>>> text = u'I don\u2018t like this'
>>> print text.encode('utf-8')
I dont like this

Herhangi bir dosyadaki her satırın unicode olarak okunacağından emin olmak için codecs.open, sadece opendosyanın kodlamasını belirtmenize izin veren sadece yerine işlevi kullanmanız daha iyi olur :

>>> import codecs
>>> f1 = codecs.open(file1, "r", "utf-8")
>>> text = f1.read()
>>> print type(text)
<type 'unicode'>
>>> print text.encode('utf-8')
I dont like this

8

Python 3 okuma yöntemini kullanarak şifreli bir metin dosyasını okumak da mümkündür:

f = open (file.txt, 'r', encoding='utf-8')
text = f.read()
f.close()

Bu varyasyonla, herhangi bir ek kitaplığı içe aktarmaya gerek yoktur


6

Ama gerçekten "Bundan hoşlanmadım", "Bundan hoşlanmadım" değil. U '\ u2018' karakteri, "" "karakterinden tamamen farklı bir karakterdir (ve görsel olarak" "karakterine daha çok karşılık gelmelidir).

Kodlanmış unicode'u düz ASCII'ye dönüştürmeye çalışıyorsanız, ASCII'ye çevirmek istediğiniz bir unicode noktalama eşlemesini tutabilirsiniz.

punctuation = {
  u'\u2018': "'",
  u'\u2019': "'",
}
for src, dest in punctuation.iteritems():
  text = text.replace(src, dest)

Unicode'da çok fazla noktalama işareti var , ancak sanırım sadece birkaçının gerçekten okuduğunuz belgeleri oluşturan uygulama tarafından kullanıldığından emin olabilirsiniz.


1
aslında, dikte eşleme Unicode sıra sayılarını Unicode sıra sayılarına ({0x2018: 0x27, 0x2019: 0x27}) yaparsanız, tüm değiştirmeyi tek seferde yapmak için tüm dikteyi text.translate () 'e iletebilirsiniz.
Thomas Wouters

3

Metin dosyanızın bozuk olduğu gerçeğini bir kenara bırakırsak (U + 2018, bir kesme işareti değil, sol tırnak işaretidir): iconv, unicode karakterleri ascii'ye çevirmek için kullanılabilir.

Modül artık desteklenmediğinden ve bunun için kanonik bir ana sayfa bulamadığım için "iconvcodec" için google yapmanız gerekecek.

>>> import iconvcodec
>>> from locale import setlocale, LC_ALL
>>> setlocale(LC_ALL, '')
>>> u'\u2018'.encode('ascii//translit')
"'"

Alternatif olarak iconv, dosyanızı temizlemek için komut satırı yardımcı programını kullanabilirsiniz:

$ xxd foo
0000000: e280 980a                                ....
$ iconv -t 'ascii//translit' foo | xxd
0000000: 270a                                     '.

2

Unicode kaçış karakterleri içeren unicode olmayan bir dizeniz olması ihtimali vardır, örneğin:

>>> print repr(text)
'I don\\u2018t like this'

Bu aslında daha önce bir kez başıma geldi. unicode_escapeDizenin kodunu unicode olarak çözmek için bir codec bileşeni kullanabilir ve ardından onu istediğiniz herhangi bir biçime kodlayabilirsiniz:

>>> uni = text.decode('unicode_escape')
>>> print type(uni)
<type 'unicode'>
>>> print uni.encode('utf-8')
I dont like this

1

Bu Pythons yolu size unicode kodlanmış dizeleri gösterir. Ama bence ekrandaki dizeyi yazdırabilmeniz veya yeni bir dosyaya sorunsuz bir şekilde yazabilmeniz gerekiyor.

>>> test = u"I don\u2018t like this"
>>> test
u'I don\u2018t like this'
>>> print test
I dont like this

1

Aslında U + 2018, özel karakterin Unicode temsilidir '. İsterseniz bu karakterin örneklerini şu kodla U + 0027'ye dönüştürebilirsiniz:

text = text.replace (u"\u2018", "'")

Ek olarak, dosyayı yazmak için ne kullanıyorsunuz? f1.read()şuna benzer bir dize döndürmelidir:

'I don\xe2\x80\x98t like this'

Bu dizeyi döndürüyorsa , dosya yanlış yazılıyor demektir:

'I don\u2018t like this'

Afedersiniz! Dediğiniz gibi geri dönüyor 'Ben böyle yapmıyorum'
Graviton

Gördüğünüz 'Ben böyle yapmıyorum', Python'a str dediği şeydir. Python'daki bir unicode örneği olan u'Ben böyle yapmıyorum 'ifadesinin utf-8 kodlaması gibi görünüyor. Birincisinde .decode ('utf-8') veya ikincisinde .encode ('utf-8') çağırmayı deneyin.
Logan

@hop: oops, forgot ord () onaltılık yerine ondalık döndürür. Yakaladığınız için teşekkürler.
John Millikin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.