Odczyt znaków z pliku w Pythonie

W pliku tekstowym znajduje się napis "I don' t like this".

Jednak, kiedy Wczytuję go do ciągu znaków, staje się "I don\xe2\x80 \ x98t like this". Rozumiem, że \u2018 jest reprezentacją unicode"'". Używam

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

Polecenie do odczytu.

Teraz, jest możliwe, aby odczytać łańcuch w taki sposób, że gdy jest wczytany do łańcucha, to jest "nie lubię tego", zamiast"I don\xe2\x80\x98t like this like this"?

Druga edycja: widziałem kilka ludzie używają mapowania do rozwiązania tego problemu, ale tak naprawdę, czy nie ma wbudowanej konwersji, która robi tego rodzaju konwersję ANSI na unicode ( i odwrotnie)?

Author: DzinX, 2008-09-29

7 answers

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

odczyt Unicode z pliku jest więc prosty:

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

możliwe jest również otwieranie plików w trybie aktualizacji, umożliwiając zarówno odczyt, jak i zapis:

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

EDIT: zakładam, że twoim celem jest po prostu poprawne odczytanie pliku do napisu w Pythonie. Jeśli próbujesz przekonwertować ciąg znaków ASCII z Unicode, to naprawdę nie ma bezpośredniego sposobu, aby to zrobić, ponieważ znaki Unicode niekoniecznie muszą istnieć w ASCII.

Jeśli próbujesz przekonwertować na ciąg znaków ASCII, spróbuj wykonać jedną z następujących czynności:

  1. Zastąp określone znaki unicode odpowiednikami ASCII, jeśli chcesz obsłużyć tylko kilka specjalnych przypadków, takich jak ten konkretny przykład

  2. Użyj unicodedata modułu normalize() i metody string.encode(), Aby przekonwertować jak najlepiej do następnego najbliższego odpowiednika ASCII (Ref 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'
    
 134
Author: Jay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-05 01:18:22

Jest kilka kwestii do rozważenia.

Znak \u2018 może pojawić się tylko jako fragment reprezentacji ciągu znaków unicode w Pythonie, np. jeśli napiszesz:

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

Teraz, jeśli chcesz po prostu wydrukować ciąg znaków unicode, użyj metody encode unicode:

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

Aby upewnić się, że każda linia z dowolnego pliku będzie odczytywana jako unicode, lepiej Użyj funkcji codecs.open zamiast tylko open, która pozwala określić kodowanie pliku:

>>> 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
 14
Author: DzinX,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-29 07:15:17

Ale to naprawdę jest "nie lubię tego", a nie "nie lubię tego". Znak u '\u2018 'jest zupełnie innym znakiem niż "' "(i wizualnie powinien odpowiadać bardziej"').

Jeśli próbujesz przekonwertować zakodowany unicode na zwykły ASCII, możesz zachować mapowanie interpunkcji unicode, które chciałbyś przetłumaczyć na ASCII.

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

Jest strasznie dużo znaków interpunkcyjnych w unicode , ale przypuszczam, że możesz liczyć na tylko kilka z nich jest faktycznie używanych przez dowolną aplikację, która tworzy dokumenty, które czytasz.

 6
Author: Logan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-29 07:00:40

Pomijając fakt, że plik tekstowy jest uszkodzony( U+2018 jest lewym cudzysłowem, a nie apostrofem): iconv może być używany do transliteracji znaków unicode do ascii.

Będziesz musiał wygooglować "iconvcodec", ponieważ moduł wydaje się już nie być obsługiwany i nie mogę znaleźć kanonicznej strony głównej dla niego.

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

Alternatywnie możesz użyć narzędzia linii poleceń iconv do czyszczenia pliku:

$ xxd foo
0000000: e280 980a                                ....
$ iconv -t 'ascii//translit' foo | xxd
0000000: 270a                                     '.
 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-30 20:10:54

Istnieje możliwość, że w jakiś sposób masz ciąg nie-unicode ze znakami escape unicode, np.:

>>> print repr(text)
'I don\\u2018t like this'
Zdarzyło mi się to już raz. Możesz użyć kodeka unicode_escape, aby dekodować ciąg znaków do unicode, a następnie kodować go do dowolnego formatu, który chcesz:
>>> uni = text.decode('unicode_escape')
>>> print type(uni)
<type 'unicode'>
>>> print uni.encode('utf-8')
I don‘t like this
 2
Author: DzinX,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-29 07:22:21

Właściwie, U+2018 jest reprezentacją Unicode znaku specjalnego". Jeśli chcesz, możesz przekonwertować instancje tego znaku na U + 0027 za pomocą tego kodu:

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

Dodatkowo, czego używasz do zapisu pliku? f1.read() powinien zwracać łańcuch, który wygląda tak:

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

Jeśli zwraca Ten łańcuch, plik jest zapisywany nieprawidłowo:

'I don\u2018t like this'
 2
Author: John Millikin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 01:02:41

To jest Pythons sposób pokazać ci Unicode zakodowane ciągi. Ale myślę, że powinieneś być w stanie wydrukować ciąg znaków na ekranie lub zapisać go do nowego pliku bez żadnych problemów.

>>> test = u"I don\u2018t like this"
>>> test
u'I don\u2018t like this'
>>> print test
I don‘t like this
 1
Author: xardias,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-29 06:54:22