Устойчива на куршуми работа с кодиране в Python

Въпросът за unicode в Python2.

Тъй като знам за това, винаги трябва да decode всичко, което чета отвън (файлове, мрежа). decode преобразува външните байтове във вътрешни низове на Python, използвайки набор от знаци, посочен в параметрите. Така че decode("utf8") означава, че външните байтове са уникод низ и те ще бъдат декодирани до низове на Python.

Също така винаги трябва да encode всичко, което пиша навън. Посочвам кодиране в параметрите на функцията encode и тя се преобразува в правилно кодиране и записва.

Тези твърдения са верни, нали?

Но понякога, когато анализирам html документи, получавам грешки при декодиране. Доколкото разбирам, документът е в друго кодиране (например cp1252) и възниква грешка, когато се опитам да декодирам това с помощта на кодиране utf8. Така че въпросът е как да напишем бронирано приложение?

Открих, че има добра библиотека, за да се предположи, че кодирането е chardet и това е единственият начин да се пише бронирано приложения. нали


person Community    schedule 03.12.2013    source източник
comment
Документът често идва някъде с изявление за неговото кодиране. Вижте дали наборът от знаци е посочен. Ако не разполагате с кодирането или ако посоченото кодирането е грешно, може да попаднете на неизбежни грешки. Най-доброто, което можете да се надявате да направите тогава, е да се справите с грешките с някаква политика и да създадете резултат, който може би изглежда като това, което искате.   -  person user2357112 supports Monica    schedule 03.12.2013
comment
Смятам, че най-добрият преглед на проблемите с кодирането в Python е следната страница: sebsauvage.net/python/snyppets/ #unicode Освен това, в публикацията ви има едно малко погрешно схващане: функцията «decode» винаги ще ви дава Unicode. Съгласен съм с предишния коментар, т.е.: разчитайте преди всичко на декларацията за набор от знаци. Наистина няма брониран начин за справяне с неправилно кодирани документи.   -  person Fred Osterrath    schedule 03.12.2013
comment
stackoverflow.com/questions/606191/ също може да помогне с това.   -  person anatoly techtonik    schedule 16.01.2017


Отговори (3)


... decode("utf8") означава, че външните байтове са уникод низ и ще бъдат декодирани до низове на Python.

...

Тези твърдения са верни, нали?

Не, външните байтове са двоични данни, те не са уникод низ. Така <str>.decode("utf8") ще произведе Python unicode обект, като интерпретира байтовете в <str> като UTF-8; може да доведе до грешка, ако байтовете не могат да бъдат декодирани като UTF-8.

Определянето на кодирането на даден документ не е непременно проста задача. Или трябва да имате някакъв външен източник на информация, който да ви казва кодирането, или трябва да знаете нещо за това, което има в документа. Например, ако знаете, че това е HTML документ с вътрешно зададено кодиране, тогава можете да анализирате документа с помощта на алгоритъм като описаната в стандарта HTML за намиране на кодирането и след това използване на това кодиране за анализиране на документа (това е двуходова операция). Въпреки това, само защото един HTML документ указва кодиране, това не означава, че той може да бъде декодиран с това кодиране. Все още може да получите грешки, ако данните са повредени или ако документът не е кодиран правилно.

Има библиотеки като chardet (виждам, че вече го споменахте), които ще се опитат да познайтекодирането на документ вместо вас (това е само предположение, не непременно правилно). Но те могат да имат свои собствени проблеми, като производителност, и може да не разпознаят кодирането на вашия документ.

person millerdev    schedule 08.12.2013
comment
Този получава моя глас; но може би подчертайте, че chardet е евристичен гадател, който не се опитва да провери дали резултатът, който съобщава, е валиден -- ще трябва да се подготвите за грешки при декодиране и може би да се върнете към второто най-добро предположение или просто да се откажете ( например неправилно конфигуриран уеб сървър може да ви сервира куп JPEG байтове, които просто нямат имат език). - person tripleee; 16.12.2015

Опитайте да опаковате функциите си в извиквания try:except:.

  • Опитайте да декодирате като utf-8:
  • Хванете изключение, ако не utf-8:
  • ако възникне изключение, опитайте следващото кодиране:
  • и т.н., и т.н.

Направете го функция, която връща str, когато (и ако) намери кодиране, което не е изключено, и връща None или празен str, когато изчерпи списъка си с кодировки и се повдигне последното изключение.

Както казаха другите, кодирането трябва да бъде записано някъде, така че първо проверете това.

Неефективно и честно казано поради моето ниво на умения, може да е далеч, но според начинаещия ми ум може да облекчи някои от проблемите при работа с неизвестно или недокументирано кодиране.

person WeRelic    schedule 08.12.2013

Преобразувайте в unicode от cp437. По този начин получавате вашите байтове точно в unicode и обратно.

person anatoly techtonik    schedule 16.12.2015
comment
Ако вие -1, кажете ако имате нужда от обяснение защо cp437. Ако просто не харесвате cp437, защото unicode е модерен, няма нищо друго. - person anatoly techtonik; 17.12.2015