Читання персонажа з файлу в Python


102

У текстовому файлі є рядок "Мені це не подобається".

Однак, коли я читаю його в рядок, він стає "я не \ xe2 \ x80 \ x98t подібний". Я розумію, що \ u2018 - це представлення унікоду "" ". я використовую

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

команда виконати читання.

Тепер, чи можна читати рядок таким чином, що коли він читається в рядку, це "мені не подобається це", а не "я не так \ xe2 \ x80 \ x98t як це подібне"?

Друга редакція: я бачив, як деякі люди використовують картування для вирішення цієї проблеми, але насправді, чи не існує вбудованої конверсії, яка робить такий тип ANSI в однокоректне (і навпаки) перетворення?


Деякі коментарі: Я бачив, як деякі люди використовують картування для вирішення цієї проблеми, але насправді, чи не існує вбудованої конверсії, яка робить такий тип ANSI у однокоректне (і навпаки) перетворення? Дякую!
Гравітон

Немає, тому що існує сотні тисяч кодів Unicode. Як би ви вирішили, який слід відобразити до символів ASCII?
Джон Міллікін

2
btw, ваш текстовий файл зламаний! U + 2018 - це "ЛІФТА ОДИНОВА ОЦІНКА ЦИТКИ", а не апостроф (найчастіше U + 0027).

Джоне, твій коментар невірний, принаймні в загальному сенсі. lib iconv може бути використаний для транслітерації символів unicode в ascii (навіть залежно від локальної точки. $ python -c 'print u "\ u2018" .encode ("utf-8")' | iconv -t 'ascii // translit' | xxd 0000000: 270a

річ у тому, що вам потрібно перетворити UNICODE в ASCII (не навпаки).
hasen

Відповіді:


157

Посилання: http://docs.python.org/howto/unicode

Отже, прочитати Unicode з файлу просто:

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

Також можна відкривати файли в режимі оновлення, дозволяючи читати і записувати:

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])

EDIT : Я припускаю, що ваша ціль - просто вміти правильно читати файл у рядок на Python. Якщо ви намагаєтеся перетворити на рядок ASCII з Unicode, то прямого способу це не існує, оскільки символи Unicode не обов'язково існуватимуть в ASCII.

Якщо ви намагаєтеся перетворити на рядок ASCII, спробуйте одне з наступних:

  1. Замініть конкретні символи unicode на еквіваленти ASCII, якщо ви хочете обробити лише кілька спеціальних випадків, таких як цей конкретний приклад

  2. Використовуйте unicodedataмодулі normalize()та string.encode()метод, щоб якнайкраще перетворити на наступний найближчий еквівалент ASCII (посилання https://web.archive.org/web/20090228203858/http://techxplorer.com/2006/07/18/converting- unicode-to-ascii-using-python ):

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

3
codecsмодуль не обробляє належним чином універсальний режим нових рядків. Використовуйте io.open()замість цього на Python 2.7+ (він побудований open()на Python 3).
jfs

15

Є кілька моментів, які слід врахувати.

Символ \ u2018 може відображатися лише як фрагмент подання рядка Unicode на Python, наприклад, якщо ви пишете:

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

Тепер, якщо ви просто хочете гарненько надрукувати рядок Unicode, просто використовуйте encodeметод unicode :

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

Щоб переконатися, що кожен рядок з будь-якого файлу читатиметься як unicode, краще використовувати codecs.openфункцію, а не просто open, яка дозволяє вказати кодування файлу:

>>> 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

6

Але це насправді "мені це не подобається", а не "мені це не подобається". Символ u '\ u2018' - це зовсім інший символ, ніж "" "(і, візуально, він повинен більше відповідати" "".

Якщо ви намагаєтеся перетворити закодований унікод в звичайний ASCII, ви, можливо, зможете зберегти відображення пунктуації унікоду, яке ви хочете перевести в ASCII.

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

Однак у Unicode є дуже багато знаків пунктуації , але я думаю, ви можете розраховувати, що лише деякі з них фактично використовуються будь-яким додатком, який створює документи, які ви читаєте.


1
насправді, якщо ви зробите мап диктату Unicode порядки на порядкові порядки Unicode ({0x2018: 0x27, 0x2019: 0x27}), ви можете просто передати весь дікт на text.translate (), щоб зробити все заміщення за один раз.
Томас Вутерс

5

Можна також прочитати закодований текстовий файл, використовуючи метод зчитування python 3:

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

З цією варіацією немає необхідності імпортувати додаткові бібліотеки


3

Залишаючи осторонь те, що ваш текстовий файл порушений (U + 2018 - лівий лапок, а не апостроф): iconv може використовуватися для транслітерації символів unicode в ascii.

Вам доведеться google для "iconvcodec", оскільки модуль, здається, більше не підтримується, і я не можу знайти канонічну домашню сторінку для нього.

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

Ви також можете скористатися iconvутилітою командного рядка, щоб очистити файл:

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

2

Існує ймовірність, що якось у вас є рядок без унікоду з символами втечі Unicode, наприклад:

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

Це насправді траплялося зі мною раніше. Ви можете використовувати unicode_escapeкодек, щоб декодувати рядок для unicode, а потім кодувати його в будь-який потрібний вам формат:

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

1

Цей спосіб Pythons показує вам, кодовані рядками unicode. Але я думаю, ви повинні мати можливість надрукувати рядок на екрані або записати його в новий файл без проблем.

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

1

Власне, U + 2018 - це представлення спеціального символу Unicode '. Якщо ви хочете, ви можете перетворити екземпляри цього символу в U + 0027 за допомогою цього коду:

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

Крім того, що ви використовуєте для написання файлу? f1.read()повинен повернути рядок, який виглядає приблизно так:

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

Якщо він повертає цей рядок, файл записується неправильно:

'I don\u2018t like this'

Вибачте! Як ви вже сказали, він повертається "Я не так \ xe2 \ x80 \ x98t, як це"
Гравітон,

"Я не можу \ xe2 \ x80 \ x98t як це", що ви бачите, це те, що Python би назвав str. Здається, це кодування utf-8 u'I don \ u2018t like this ", що є екземпляром Unicode в Python. Спробуйте зателефонувати .decode ('utf-8') на першому або .encode ('utf-8') на другому.
Логан

@hop: oops, забув ord () повертає десятковий замість шестигранної. Дякую за улов.
Джон Міллікін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.