Mam problem z mózgiem w rozumieniu czytania i pisania tekstu do pliku (Python 2.4).
# The string, which has an a-acute in it.
ss = u'Capit\xe1n'
ss8 = ss.encode('utf8')
repr(ss), repr(ss8)
(„u'Capit \ xe1n” ”,„ Capit \ xc3 \ xa1n ”)
print ss, ss8
print >> open('f1','w'), ss8
>>> file('f1').read()
'Capit\xc3\xa1n\n'
Więc wpisuję Capit\xc3\xa1n
do mojego ulubionego edytora, w pliku f2.
Następnie:
>>> open('f1').read()
'Capit\xc3\xa1n\n'
>>> open('f2').read()
'Capit\\xc3\\xa1n\n'
>>> open('f1').read().decode('utf8')
u'Capit\xe1n\n'
>>> open('f2').read().decode('utf8')
u'Capit\\xc3\\xa1n\n'
Czego tu nie rozumiem? Najwyraźniej brakuje mi trochę magii (lub rozsądku). Co wpisuje się w pliki tekstowe, aby uzyskać prawidłowe konwersje?
To, czego naprawdę nie rozumiem tutaj, to, o co chodzi w reprezentacji UTF-8, jeśli nie możesz tak naprawdę przekonać Pythona do rozpoznania go, gdy pochodzi on z zewnątrz. Może powinienem po prostu JSON zrzucić ciąg i użyć go zamiast tego, ponieważ ma on reprezentatywną reprezentację! Co więcej, czy istnieje reprezentacja ASCII tego obiektu Unicode, który Python rozpozna i zdekoduje po przejściu z pliku? Jeśli tak, jak to zdobyć?
>>> print simplejson.dumps(ss)
'"Capit\u00e1n"'
>>> print >> file('f3','w'), simplejson.dumps(ss)
>>> simplejson.load(open('f3'))
u'Capit\xe1n'
u'\xe1'
jest jednym kodem Unicode,U+00e1
który może być reprezentowany przy użyciu 1 lub więcej bajtów w zależności od kodowania znaków (w utf-8 jest to 2 bajty).b'\xe1'
to jeden bajt (liczba 225), jaka litera, jeśli jakąkolwiek może reprezentować, zależy od kodowania znaków użytego do jej zdekodowania, np. jestб
(U+0431
) w cp1251,с
(U+0441
) w cp866 itp.Zamiast zadzierać z metodami kodowania i dekodowania, łatwiej jest mi określić kodowanie podczas otwierania pliku.
io
Moduł (dodawane w Pythonie 2.6) zapewniaio.open
funkcję, która zawiera parametr kodowania.Użyj metody otwartej z
io
modułu.Następnie po wywołaniu funkcji read () f zwracany jest zakodowany obiekt Unicode.
Zauważ, że w Pythonie 3
io.open
funkcja jest aliasem dla wbudowanejopen
funkcji. Wbudowana funkcja otwarta obsługuje tylko argument kodowania w Pythonie 3, a nie Python 2.Edycja: Wcześniej ta odpowiedź zalecała moduł kodeków . Moduł kodeki mogą powodować problemy podczas mieszania
read()
ireadline()
tak ta odpowiedź teraz zaleca io moduł zamiast.Użyj metody otwartej z modułu kodeków.
Następnie po wywołaniu funkcji read () f zwracany jest zakodowany obiekt Unicode.
Jeśli znasz kodowanie pliku, użycie pakietu kodeków będzie znacznie mniej skomplikowane.
Zobacz http://docs.python.org/library/codecs.html#codecs.open
źródło
open(file,'w')
docodecs.open(file,'w','utf-8')
rozwiązaniacodecs.open(...)
metoda jest również w pełni zgodna zewith open(...):
stylem, w którymwith
dbanie o zamknięcie pliku jest już zrobione? Wygląda na to, że i tak działa.with codecs.open(...) as f:
cały czas.Teraz wszystko czego potrzebujesz w Python3 to
open(Filename, 'r', encoding='utf-8')
[Edytuj w dniu 02.02.2016 r. W celu uzyskania wyjaśnień]
Python3 dodał parametr kodowania do swojej funkcji otwartej. Tutaj zebrano następujące informacje o funkcji otwartej: https://docs.python.org/3/library/functions.html#open
Tak więc, dodając
encoding='utf-8'
jako parametr do funkcji open, odczyt i zapis pliku odbywa się jako utf8 (który jest teraz również domyślnym kodowaniem wszystkiego, co dzieje się w Pythonie).źródło
codecs.open('somefile', encoding='utf-8')
stackoverflow.com/a/147756/149428Więc znalazłem rozwiązanie tego, czego szukam, a mianowicie:
Przydaje się kilka niezwykłych kodeków. Ten konkretny odczyt umożliwia pobranie reprezentacji UTF-8 z poziomu Pythona, skopiowanie ich do pliku ASCII i odczytanie ich do Unicode. Pod dekodą „string-escape” ukośniki nie zostaną podwojone.
Pozwala to na taką podróż w obie strony, jaką sobie wyobrażałem.
źródło
(codecs.open(file,"r","utf-8")
i po prostuopen(file,"r").read().decode("utf-8")
oba działały idealnie.źródło
Właściwie to działało dla mnie do odczytu pliku z kodowaniem UTF-8 w Pythonie 3.2:
źródło
Aby przeczytać ciąg Unicode, a następnie wysłać do HTML, zrobiłem to:
Przydatne w przypadku serwerów http zasilanych przez Pythona.
źródło
Natknąłeś się na ogólny problem z kodowaniem: Jak mogę stwierdzić, w którym kodowaniu jest plik?
Odpowiedź: Nie możesz tego zrobić, chyba że format pliku to zapewnia. Na przykład XML zaczyna się od:
Ten nagłówek został starannie wybrany, aby można go było odczytać bez względu na kodowanie. W twoim przypadku nie ma takiej wskazówki, dlatego ani twój redaktor, ani Python nie mają pojęcia, co się dzieje. Dlatego musisz użyć
codecs
modułu i użyćcodecs.open(path,mode,encoding)
który zapewnia brakujący bit w Pythonie.Jeśli chodzi o edytor, musisz sprawdzić, czy oferuje on sposób na ustawienie kodowania pliku.
Celem UTF-8 jest możliwość kodowania 21-bitowych znaków (Unicode) jako 8-bitowego strumienia danych (ponieważ jest to jedyna rzecz, którą wszystkie komputery na świecie mogą sobie poradzić). Ponieważ jednak większość systemów operacyjnych pochodzi z epoki Unicode, nie mają one odpowiednich narzędzi do dołączania informacji o kodowaniu do plików na dysku twardym.
Kolejnym problemem jest reprezentacja w Pythonie. To doskonale wyjaśniono w komentarzu heikogerlach . Musisz zrozumieć, że twoja konsola może wyświetlać tylko ASCII. Aby wyświetlić Unicode lub cokolwiek> = kod znakowy 128, musi użyć jakiegoś sposobu zmiany znaczenia. W edytorze nie wolno wpisywać uciekającego łańcucha wyświetlanego, ale jego znaczenie (w tym przypadku należy wprowadzić umlaut i zapisać plik).
To powiedziawszy, możesz użyć funkcji eval () Pythona, aby przekształcić łańcuch znaków w ciąg znaków:
Jak widać, ciąg „\ xc3” został przekształcony w pojedynczy znak. Jest to teraz 8-bitowy ciąg kodowany w UTF-8. Aby uzyskać Unicode:
Gregg Lind zapytał: Myślę, że brakuje tutaj niektórych elementów: plik f2 zawiera: hex:
codecs.open('f2','rb', 'utf-8')
, na przykład czyta je wszystkie w osobnych znakach (oczekiwane) Czy istnieje jakiś sposób zapisu do pliku w ASCII, który by działał?Odpowiedź: To zależy od tego, co masz na myśli. ASCII nie może reprezentować znaków> 127. Dlatego potrzebujesz sposobu, aby powiedzieć „kilka następnych znaków oznacza coś specjalnego”, co robi sekwencja „\ x”. Mówi: Następne dwa znaki to kod jednego znaku. „\ u” robi to samo, używając czterech znaków do kodowania Unicode do 0xFFFF (65535).
Nie możesz więc bezpośrednio pisać Unicode do ASCII (ponieważ ASCII po prostu nie zawiera tych samych znaków). Możesz pisać jako znaki ucieczki (jak w f2); w takim przypadku plik może być reprezentowany jako ASCII. Możesz też napisać go jako UTF-8, w takim przypadku potrzebujesz 8-bitowego bezpiecznego strumienia.
Użyte rozwiązanie
decode('string-escape')
działa, ale musisz pamiętać, ile pamięci zużywasz: trzy razy więcej niż używaszcodecs.open()
.Pamiętaj, że plik jest tylko sekwencją bajtów z 8 bitami. Ani bity, ani bajty nie mają znaczenia. To ty mówisz „65” oznacza „A”. Ponieważ
\xc3\xa1
powinno stać się „à”, ale komputer nie ma możliwości wiedzieć, musisz to powiedzieć, określając kodowanie, które zostało użyte podczas zapisywania pliku.źródło
z wyjątkiem tego
codecs.open()
, że można używaćio.open()
do pracy z Python2 lub Python3 do odczytu / zapisu pliku Unicodeprzykład
źródło
with io.open('data.txt', 'w', 'utf-8') as file:
i got błąd:TypeError: an integer is required
. Po tym, jak się zmieniłemwith io.open('data.txt', 'w', encoding='utf-8') as file:
i działało.Cóż, twój ulubiony edytor tekstu nie zdaje sobie sprawy, że
\xc3\xa1
powinny to być dosłowne znaki, ale interpretuje je jako tekst. Dlatego w ostatnim wierszu pojawia się podwójny ukośnik odwrotny - jest to teraz prawdziwy odwrotny ukośnik +xc3
itp. W twoim pliku.Jeśli chcesz czytać i zapisywać zakodowane pliki w Pythonie, najlepiej użyj modułu kodeków .
Wklejanie tekstu między terminalem a aplikacjami jest trudne, ponieważ nie wiesz, który program zinterpretuje tekst za pomocą jakiego kodowania. Możesz spróbować:
Następnie wklej ten ciąg do edytora i upewnij się, że przechowuje go za pomocą Latin-1. Przy założeniu, że schowek nie niszczy sznurka, podróż w obie strony powinna działać.
źródło
Sekwencja \ x .. jest specyficzna dla Pythona. To nie jest uniwersalna sekwencja bajtów.
To, jak faktycznie wprowadzasz kodowanie UTF-8 w formacie innym niż ASCII, zależy od systemu operacyjnego i / lub edytora. Oto jak to zrobić w systemie Windows . Dla OS X, aby wprowadzić z ostrym akcentem można po prostu hit + , a następnie , i prawie wszystkie edytory tekstu na poparcie OS X UTF-8.optionEA
źródło
Możesz także ulepszyć oryginalną
open()
funkcję do pracy z plikami Unicode, zastępując ją w miejscu za pomocąpartial
funkcji. Zaletą tego rozwiązania jest to, że nie musisz zmieniać żadnego starego kodu. Jest przezroczysty.źródło
Próbowałem parsować iCal przy użyciu Python 2.7.9:
Ale dostawałem:
i zostało to naprawione za pomocą:
(Teraz można wydrukować liké á böss.)
źródło
Znalazłem najprostsze podejście, zmieniając domyślne kodowanie całego skryptu na „UTF-8”:
każdy
open
,print
lub inne oświadczenie będzie po prostu używaćutf8
.Działa przynajmniej dla
Python 2.7.9
.Thx idzie na https://markhneedham.com/blog/2015/05/21/python-unicodeencodeerror-ascii-codec-cant-encode-character-uxfc-in-position-11-ordinal-not-in-range128/ ( spójrz na koniec).
źródło