Чтение символов из файла в Python

В текстовом файле есть строка «Мне это не нравится».

Однако, когда я считываю это в строке, это становится «Я не \ xe2 \ x80 \ x98t как это». Я понимаю, что \ u2018 является представлением "'" в Юникоде. я использую

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

команда для чтения.

Теперь, возможно ли прочитать строку таким образом, чтобы, когда она считывалась в строке, это было «Мне это не нравится» вместо «Я не \ xe2 \ x80 \ x98t вот так вот так»?

Второе редактирование: я видел, как некоторые люди использовали сопоставление для решения этой проблемы, но на самом деле нет встроенного преобразования, которое выполняет такое преобразование ANSI в Unicode (и наоборот)?


person Graviton    schedule 29.09.2008    source источник
comment
Некоторые комментарии: Я видел, как некоторые люди использовали сопоставление для решения этой проблемы, но на самом деле нет встроенного преобразования, которое выполняет преобразование такого типа из ANSI в Unicode (и наоборот)? Спасибо!   -  person Graviton    schedule 29.09.2008
comment
Нет, потому что существуют сотни тысяч кодовых точек Unicode. Как бы вы решили, какие символы ASCII следует сопоставить?   -  person John Millikin    schedule 29.09.2008
comment
кстати, ваш текстовый файл сломан! U + 2018 - ЛЕВЫЙ ОДИНОЧНЫЙ ЗНАК, а не апостроф (чаще всего U + 0027).   -  person    schedule 30.09.2008
comment
Джон, ваш комментарий неверен, по крайней мере, в общем смысле. iconv lib можно использовать для транслитерации символов Юникода в ascii (даже в зависимости от локали. $ python -c 'print u \ u2018.encode (utf-8)' | iconv -t 'ascii // translit' | xxd 0000000: 270a   -  person    schedule 30.09.2008
comment
дело в том, что вам нужно преобразовать UNICODE в ASCII (а не наоборот).   -  person hasen    schedule 08.12.2008


Ответы (9)


Ссылка: 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])

ИЗМЕНИТЬ: я предполагаю, что ваша намеченная цель - просто правильно прочитать файл в строке в Python. Если вы пытаетесь преобразовать в строку ASCII из Unicode, тогда на самом деле нет прямого способа сделать это, поскольку символы Unicode не обязательно будут существовать в ASCII.

Если вы пытаетесь преобразовать в строку ASCII, попробуйте одно из следующих действий:

  1. Замените определенные символы Unicode эквивалентами ASCII, если вы хотите обрабатывать только несколько особых случаев, таких как этот конкретный пример.

  2. Используйте normalize() модуля unicodedata и метод string.encode() для максимального преобразования в следующий ближайший эквивалент ASCII (Ref https://web.archive.org/web/20090228203858/http://techxplorer.com/18июля2006г./convert-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'
    
person Jay    schedule 29.09.2008
comment
codecs модуль неправильно обрабатывает универсальный режим новой строки. Вместо этого используйте io.open() в Python 2.7+ (он встроен open() в Python 3). - person jfs; 05.06.2015

Следует учесть несколько моментов.

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

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

Теперь, если вы просто хотите красиво распечатать строку Unicode, просто используйте метод unicode encode:

>>> text = u'I don\u2018t like this'
>>> print text.encode('utf-8')
I don‘t 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 don‘t like this
person DzinX    schedule 29.09.2008

Также можно прочитать закодированный текстовый файл с помощью метода чтения python 3:

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

В этом варианте нет необходимости импортировать какие-либо дополнительные библиотеки.

person Stein    schedule 29.11.2018

Но на самом деле это «мне это не нравится», а не «мне это не нравится». Символ u '\ u2018' - это совершенно другой символ, чем "'" (и визуально должен больше соответствовать' '').

Если вы пытаетесь преобразовать закодированный Unicode в простой ASCII, вы, возможно, могли бы сохранить отображение знаков препинания Unicode, которое вы хотели бы перевести в ASCII.

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

Однако в юникоде очень много знаков препинания, но я полагаю, вы можете рассчитывать на то, что лишь некоторые из них действительно будут использоваться любым приложением, создающим документы, которые вы читаете.

person Logan    schedule 29.09.2008
comment
на самом деле, если вы сделаете dict сопоставление порядковых номеров Unicode с порядковыми номерами Unicode ({0x2018: 0x27, 0x2019: 0x27}), вы можете просто передать весь dict в text.translate (), чтобы выполнить всю замену за один раз. - person Thomas Wouters; 29.09.2008

Существует вероятность того, что у вас есть строка, отличная от Unicode, с escape-символами Unicode, например:

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

На самом деле это однажды случилось со мной. Вы можете использовать кодек unicode_escape для декодирования строки в Юникод, а затем закодировать ее в любой желаемый формат:

>>> uni = text.decode('unicode_escape')
>>> print type(uni)
<type 'unicode'>
>>> print uni.encode('utf-8')
I don‘t like this
person DzinX    schedule 29.09.2008

Не говоря уже о том, что ваш текстовый файл поврежден (U + 2018 - это левая кавычка, а не апостроф): iconv можно использовать для транслитерации символов Юникода в 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                                     '.
person Community    schedule 30.09.2008

Это способ Python показать вам строки в кодировке Unicode. Но я думаю, вы сможете без проблем распечатать строку на экране или записать ее в новый файл.

>>> test = u"I don\u2018t like this"
>>> test
u'I don\u2018t like this'
>>> print test
I don‘t like this
person xardias    schedule 29.09.2008

Фактически, U + 2018 - это Unicode-представление специального символа ‘. Если хотите, вы можете преобразовать экземпляры этого символа в U + 0027 с помощью этого кода:

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

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

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

Если он возвращает эту строку, файл записывается неправильно:

'I don\u2018t like this'
person John Millikin    schedule 29.09.2008
comment
Прости! Как вы сказали, он возвращает "Мне не \ xe2 \ x80 \ x98t это нравится" - person Graviton; 29.09.2008
comment
То, что вы видите «Мне это не нравится \ xe2 \ x80 \ x98t», - это то, что Python назвал бы str. Похоже, это кодировка utf-8 для u'I don \ u2018t like this ', которая является экземпляром Unicode в Python. Попробуйте вызвать .decode ('utf-8') для первого или .encode ('utf-8') для второго. - person Logan; 29.09.2008
comment
@hop: упс, забыл, ord () возвращает десятичное число вместо шестнадцатеричного. Спасибо за улов. - person John Millikin; 01.10.2008

Не уверен насчет опции (errors = ignore), но, похоже, она работает для файлов со странными символами Unicode.

with open(fName, "rb") as fData:
    lines = fData.read().splitlines()
    lines = [line.decode("utf-8", errors="ignore") for line in lines]
person nvd    schedule 02.01.2021