2010-07-20 9 views
9

Chciałem url kodować ciąg python i dostałem wyjątki z hebrajskimi ciągami. Nie mogłem tego naprawić i zacząłem programowanie zorientowane na odgadywanie. Wreszcie, wykonując mystr = mystr.encode("utf8") przed wysłaniem go do enkodera url, zapisano dzień.Python: co naprawia "..." .okodować ("utf8")?

Czy ktoś może wyjaśnić, co się stało? Do czego służy .encode ("utf8")? Mój pierwotny ciąg był ciągiem unicode w każdym razie (tj. Poprzedzony przez u).

+9

To nie jest bezpośredni komunikat, ale ten tekst jest wart przeczytania: [Absolutne minimum Każdy programista absolutnie, pozytywnie musi wiedzieć o Unicode i zestawach znaków (bez wymówek!)] (Http: //www.joelonsoftware. com/articles/Unicode.html) autorstwa Joela Spolsky'ego – balpha

+8

Programowanie zorientowane na domysły. To jest popularny paradygmat :) – Amnon

+0

Z mojego doświadczenia wynika, że ​​poznanie podstaw (jak tu robisz) jest bardziej skuteczne. – Amnon

Odpowiedz

9

Oryginalny ciąg znaków był obiektem unicode zawierającym surowe punkty kodowe Unicode, po zakodowaniu go jako UTF-8 jest to normalny ciąg bajtów zawierający dane zakodowane w postaci UTF-8.

Enkodowanie adresu URL wydaje się oczekiwać ciągu bajtów, dzięki czemu może kodować URL jeden bajt po drugim i nie musi zajmować się kodami Unicode. Kiedy podasz mu obiekt unicode, spróbuje on przekonwertować go na ciąg bajtowy używając domyślnego kodowania, prawdopodobnie ASCII. W przypadku znaków hebrajskich, które nie mogą być reprezentowane jako ASCII, spowoduje to błędy.

1

"...". Encode ("utf-8") przekształca reprezentację napisu w pamięci na ciąg znaków zakodowany w UTF-8.

Enkoder URL prawdopodobnie oczekuje testu bytowego, czyli reprezentacji ciągów, gdzie każda postać jest reprezentowana przez jeden bajt.

0

Zwraca kodowaną w UTF-8 wersję ciągu znaków Unicode, mystr. Ważne jest, aby zdać sobie sprawę, że UTF-8 to po prostu 1 sposób kodowania Unicode. Python może pracować z wieloma innymi kodowaniami (np. Mystr.encode ("utf32") lub nawet mystr.encode ("ascii")).

0

The link, że balpha wysłany wyjaśnia to wszystko. W skrócie:

Fakt, że twój ciąg został poprzedzony prefiksem "u", oznacza, że ​​składa się on z Unicode znaków (lub punktów kodowych). UTF-8 to kodowanie tego ciągu znaków w sekwencji bajtów.

13

Mój pierwotny ciąg był ciągiem znaków Unicode anyways (tj poprzedzony u)

... co jest problemem. Nie był to "ciąg" jako taki, ale "obiekt Unicode". Zawiera sekwencję punktów kodowych Unicode. Te punkty kodowe muszą oczywiście mieć wewnętrzną reprezentację, o której Python wie, ale cokolwiek to jest, jest usuwane i są one wyświetlane jako \uXXXX, gdy jesteś print repr(my_u_str).

Aby uzyskać ciąg bajtów zrozumiałych dla innego programu, należy wykonać tę sekwencję punktów kodowych Unicode i zakodować ją. Musisz zdecydować o kodowaniu, ponieważ jest wiele do wyboru. UTF8 i UTF16 są często wybierane. ASCII może być również, jeśli pasuje. u"abc".encode('ascii') działa dobrze.

Czy my_u_str = u"\u2119ython" a następnie type(my_u_str) i type(my_u_str.encode('utf8')) aby zobaczyć różnicę w rodzaju: pierwsza to <type 'unicode'> a drugi <type 'str'>. (W każdym razie w Pythonie 2.5 i 2.6).

W Pythonie 3 sprawy wyglądają inaczej, ale ponieważ rzadko go używam, rozmawiałbym z moim kapeluszem, gdybym próbował powiedzieć coś autorytatywnego na ten temat.

+0

+1 Doskonałe wyjaśnienie. –

+0

[This] (https://tools.ietf.org/html/rfc3986) wydaje się implikować utf-8 dla wszystkiego, co nie jest już ASCII, plus jeśli pochodzi z w3schools, o których wiemy, że nie ma autorytetu. w3fools.com – stommepoes

4

Co robi .encode ("utf8")?

To zależy od tego, która wersja Pythona używasz:

  • w Pythonie 3.x, to konwertuje str obiekt (kodowany w UTF-16 lub UTF-32) w bytes obiektu zawierające reprezentację ciągu znaków w UTF-8.
  • W języku Python 2.x konwertuje obiekt unicode do obiektu str zakodowanego w UTF-8. Ale str ma również metodę encode, a pisanie '...'.encode('UTF-8') jest równoważne pisaniu '...'.decode('ascii').encode('UTF-8').

Ponieważ wspomniałeś prefiks "u", musisz używać 2.x. Jeśli nie potrzebujesz bibliotek tylko w wersji 2.x, polecam przejście na wersję 3.x, która ma ładne wyraźne rozróżnienie między tekstem a danymi binarnymi.

Dive into Python 3 ma dobre wyjaśnienie problemu.

Czy ktoś może wyjaśnić, co się stało?

Pomoże nam, jeśli powiesz nam, co było komunikatem o błędzie.

Funkcja urllib.quote oczekuje obiektu str. Zdarza się również, że działa z obiektami unicode, które zawierają tylko znaki ASCII, ale nie zawierają znaków hebrajskich.

Pythona 3.x urllib.parse.quote przyjmuje zarówno str (= Pythona 2.x unicode) i bytes obiektów. Ciągi są automatycznie kodowane w UTF-8.