UnicodeEncodeError: 'ascii' кодек не може кодувати символ u '\ xef' у позиції 0: порядковий номер не в діапазоні (128)


75

Я хочу проаналізувати свій XML-документ. Отже, я зберігав свій XML-документ, як показано нижче

class XMLdocs(db.Expando):  
   id = db.IntegerProperty()    
   name=db.StringProperty()  
   content=db.BlobProperty()  

Тепер мій нижче мій код

parser = make_parser()     
curHandler = BasketBallHandler()  
parser.setContentHandler(curHandler)  
for q in XMLdocs.all():  
        parser.parse(StringIO.StringIO(q.content))

Я отримую нижче помилки

'ascii' codec can't encode character u'\xef' in position 0: ordinal not in range(128)
Traceback (most recent call last):  
  File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/__init__.py", line 517, in __call__
    handler.post(*groups)   
  File "/base/data/home/apps/parsepython/1.348669006354245654/mapreduce/base_handler.py", line 59, in post
    self.handle()   
  File "/base/data/home/apps/parsepython/1.348669006354245654/mapreduce/handlers.py", line 168, in handle
    scan_aborted = not self.process_entity(entity, ctx)   
  File "/base/data/home/apps/parsepython/1.348669006354245654/mapreduce/handlers.py", line 233, in process_entity
    handler(entity)   
  File "/base/data/home/apps/parsepython/1.348669006354245654/parseXML.py", line 71, in process
    parser.parse(StringIO.StringIO(q.content))   
  File "/base/python_runtime/python_dist/lib/python2.5/xml/sax/expatreader.py", line 107, in parse
    xmlreader.IncrementalParser.parse(self, source)   
  File "/base/python_runtime/python_dist/lib/python2.5/xml/sax/xmlreader.py", line 123, in parse
    self.feed(buffer)  
  File "/base/python_runtime/python_dist/lib/python2.5/xml/sax/expatreader.py", line 207, in feed
    self._parser.Parse(data, isFinal)   
  File "/base/data/home/apps/parsepython/1.348669006354245654/parseXML.py", line 136, in characters   
    print ch   
UnicodeEncodeError: 'ascii' codec can't encode character u'\xef' in position 0: ordinal not in range(128)   

2
Ваша стек-траса показує, що ваш виконуваний код відрізняється від того, що ви вставили - і що ви використовуєте print. Не використовуйте друк у програмі WSGI!
Нік Джонсон,

Відповіді:


30

Здається, ви натискаєте позначку порядку байтів UTF-8 (BOM). Спробуйте використати цей рядок унікоду з вилученою специфікацією:

import codecs

content = unicode(q.content.strip(codecs.BOM_UTF8), 'utf-8')
parser.parse(StringIO.StringIO(content))

Я використовував stripзамість цього, lstripоскільки у вашому випадку у вас було кілька випадків специфікації, можливо, через конкатенований вміст файлу.


Я зробив саме так, як згадано у відповіді, але, отримавши вищезазначену помилку, спочатку це дало мені позицію 0, про яку йдеться, а тепер вона дає мені позицію 5785, згадану в попередньому коментарі
mahesh

Я рекомендую конвертувати будь-який рядок, sщо спричиняє помилку s = unicode(s.strip(codecs.BOM_UTF8), 'utf-8'). sпосилається на назву ваших рядків.
Tugrul Ates

Спробуйте замінити lstripна strip.
Tugrul Ates

Я розумію, що ви пропонуєте, і я докладно зробив ту ж помилку: ascii 'кодек не може кодувати символ u' \ xef 'у позиції 5785: порядковий номер не в діапазоні (128)
mahesh

1
Це помилка кодування під час перетворення унікоду в рядок під час друку. Він не буде містити специфікацію UTF-8, його неможливо декодувати назад до Unicode, і помилка полягає в тому, що він містить символи, що не належать до ASCII - їх видалення призведе до порушення вмісту, і специфікація техніки є лише однією з них.
Рош Оксиморон

112

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

Найшвидше однорядкове рішення - кодувати все, що ви друкуєте, до ASCII, що ваш термінал майже напевно приймає, відкидаючи символи, які ви не можете надрукувати:

print ch #fails
print ch.encode('ascii', 'ignore')

Краще рішення - змінити кодування терміналу на utf-8 і кодувати все як utf-8 перед друком. Ви повинні мати звичку думати про своє кодування Unicode КОЖНИЙ раз, коли друкуєте або читаєте рядок.


1
у моєму випадку я друкував потік twitter на терміналі, і він працював нормально. Потім я хотів перенаправити вихідні дані програм у файл, і я почав отримувати кодек 'ascii' не може кодувати символи в позиції 32-36. Пізніше, як і у цій відповіді, я використовував print tweet.encode ("utf-8", ігнорувати), і все працювало.
kommradHomer

57

Просто розміщення .encode('utf-8')в кінці об'єкта зробить роботу в останніх версіях Python.


3
Що ви маєте на увазі під "останніми версіями Python"? Тільки 3.x, чи також 2.7?
kramer65

1
Python 2.7 є явно недавнім, оскільки він все ще широко використовується.
tmthyjames

1
Працює у мене на Python 2.7
Зірка


8

Проблема відповідно до вашого відстеження - це printвислів у рядку 136 з parseXML.py. На жаль, ви не вважали за потрібне опублікувати цю частину коду, але я збираюся здогадуватися, що вона просто там для налагодження. Якщо ви зміните його на:

print repr(ch)

тоді ви повинні принаймні побачити, що ви намагаєтеся надрукувати.


2
-1 для рішення, яке не стосується Unicode, для очевидної проблеми кодування Unicode.
Триптих

7
Проблема кодування Unicode пов’язана з оператором print. Так, можуть бути й інші проблеми, але вирішення проблеми, пов’язаної з відбитком друку, є безпосередньою проблемою.
Duncan

7

Проблема в тому, що ви намагаєтеся надрукувати символ Unicode на можливо не-unicode терміналі. Вам потрібно закодувати його з 'replaceопцією перед друком, наприклад print ch.encode(sys.stdout.encoding, 'replace').


друк не є важливим, головне твердження для мене, де я отримую помилку, - це синтаксичний аналіз
mahesh

3
@Mahesh: Проблему викликає ВАШ код, у рядку 136 parseXML.py - або виправте це самостійно, або покажіть нам ту частину коду, щоб ми могли вам допомогти.
John Machin

-1

Найпростішим рішенням для подолання цієї проблеми є встановлення кодування за замовчуванням на utf8. Наслідуйте приклад

import sys

reload(sys)
sys.setdefaultencoding('utf8')


Ви можете пояснити причину?
Шафік

У моєму коментарі є посилання, яке це пояснює. По суті, бібліотеки очікують, що значення за замовчуванням asciiзалишатиметься за замовчуванням. Саме тому, setdefaultencodingяк правило, не доступний без reloadфокусу.
Марк Толонен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.