UnicodeEncodeError: кодек «ascii» не может кодировать символ в функции печати - PullRequest
0 голосов
/ 04 февраля 2019

Моя компания использует базу данных, и я пишу сценарий, который взаимодействует с этой базой данных.Уже есть сценарий для помещения запроса в базу данных и на основе запроса этот сценарий будет возвращать результаты из базы данных.

Я работаю в среде Unix и использую этот сценарий в своем сценарии для получения некоторых данных избазы данных, и я перенаправляю результат запроса в файл.Теперь, когда я пытаюсь прочитать этот файл, я получаю сообщение об ошибке:

UnicodeEncodeError: 'ascii' codec can't encode character '\u2013' in position 9741: ordinal not in range(128)

Я знаю, что python не может прочитать файл из-за кодировки файла.Кодировка файла не ascii, поэтому ошибка приходит.Я попытался проверить кодировку файла и попытался прочитать файл с его собственной кодировкой.

Код, который я использую, это-

 os.system("Query.pl \"select title from bug where (ste='KGF-A' AND ( status = 'Not_Approved')) \">patchlet.txt")
 encoding_dict3={}
 encoding_dict3=chardet.detect(open("patchlet.txt", "rb").read())
 print(encoding_dict3)
# Open the patchlet.txt file for storing the last part of titles for latest ACF in a list
 with codecs.open("patchlet.txt",encoding='{}'.format(encoding_dict3['encoding'])) as csvFile
readCSV = csv.reader(csvFile,delimiter=":")
    for row in readCSV:
        if len(row)!=0:
            if len(row) > 1:
                j=len(row)-1
                patchlets_in_latest.append(row[j])
            elif len(row) ==1:
                patchlets_in_latest.append(row[0])               
patchlets_in_latest_list=[]
# calling the strip_list_noempty function for removing newline and whitespace characters
patchlets_in_latest_list=strip_list_noempty(patchlets_in_latest)
# coverting list of titles in set to remove any duplicate entry if present
patchlets_in_latest_set= set(patchlets_in_latest_list)
# Finding duplicate entries in  list
duplicates_in_latest=[k for k,v in Counter(patchlets_in_latest_list).items() if v>1]
# Printing imp info for logs
    print("list of titles of patchlets in latest list are : ")
for i in patchlets_in_latest_list:
   **print(str(i))**
print("No of patchlets in latest list are : {}".format(str(len(patchlets_in_latest_list))))

Где Query.pl - это скрипт perl, которыйнаписано, чтобы принести результат запроса из базы данных. Кодировка, которую я получаю для "patchlet.txt" (файл, используемый для хранения результатов из HSD):

{'encoding': 'Windows-1252', 'confidence': 0.73, 'language': ''}

Даже когда я предоставилта же самая кодировка для чтения файла, тогда также я получаю ошибку.

Пожалуйста, помогите мне в решении этой ошибки.

РЕДАКТИРОВАТЬ: Я использую python3,6

РЕДАКТИРОВАТЬ2:

При выводе результата я получаю ошибку ив файле есть одна строка с неизвестным символом.Строка выглядит так:

Некоторая ошибка, из-за которой vtrace не может использоваться вместе с какой-либо трассировкой.

Я использую gvim, а в gvim "vtrace" выглядит так"~ Vvtrace".Затем я проверил в базе данных вручную этот символ, и символ «-», который в соответствии с моей клавиатурой не является ни дефисом, ни подчеркиванием. Эти типы символов создают проблему.

Также я работаю в среде Linux.

РЕДАКТИРОВАТЬ 3: Я добавил больше кода, который может помочь в отслеживании ошибки.Также я выделил «print» заявление (print(str(i))), где я получаю сообщение об ошибке.

1 Ответ

0 голосов
/ 08 февраля 2019

Проблема

Основываясь на информации в вопросе, программа обрабатывает входные данные не в формате ASCII, но не может выводить данные не в формате ASCII.

В частности, этот код:

for i in patchlets_in_latest_list:
   print(str(i))

Результаты в этом исключении:

UnicodeEncodeError: кодек 'ascii' не может кодировать символ '\ u2013'

Такое поведение было распространено в Python2, где вызов str для объекта unicode заставил бы Python попытаться закодировать объект как ASCII, в результате чего UnicodeEncodeError, если объект содержал символы не-ASCII.

В Python3 вызов str для экземпляра str не вызывает никакой кодировки.Однако вызов функции print для str закодирует str в sys.stdout.encoding.sys.stdout.encoding по умолчанию возвращается locale.getpreferredencoding .Как правило, это будет переменная окружения вашего пользователя linux LANG.

Решение

Если мы предположим, что ваша программа не переопределяет нормальное поведение кодирования, проблема должна быть решенагарантируя, что код выполняется интерпретатором Python3 в локали UTF-8.

  • быть 100% уверенным, что код выполняется интерпретатором Python3 - выведите sys.version_info из в программе .
  • попробуйте установить переменную окружения PYTHONIOENCODING при запуске скрипта: PYTHONIOENCODING=UTF-8 python3 myscript.py
  • проверьте ваш языковой стандарт с помощью команды locale в терминале (или echo $LANG).Если это не заканчивается на UTF-8, рассмотрите возможность его изменения.Обратитесь к системным администраторам, если вы работаете на корпоративной машине.
  • , если ваш код выполняется в задании cron, имейте в виду, что задания cron часто выполняются с языковым стандартом C или POSIX, который может быть использованКодировка ASCII - если явно не указан языковой стандарт.Аналогичным образом, если скрипт запускается от имени другого пользователя, проверьте его языковые настройки.

Обходной путь

Если изменение среды невозможно, вы можете обойтипроблема в Python путем кодирования в ASCII с обработчиком ошибок, а затем декодирования обратно в str.

В вашей конкретной ситуации есть четыре полезных обработчика ошибок, их влияние демонстрируется с помощью этого кода:

>>> s = 'Hello \u2013 World'
>>> s
'Hello – World'
>>> handlers = ['ignore', 'replace', 'xmlcharrefreplace', 'namereplace']
>>> print(str(s))
Hello – World
>>> for h in handlers:
...     print(f'Handler: {h}:', s.encode('ascii', errors=h).decode('ascii'))
... 
Handler: ignore: Hello  World
Handler: replace: Hello ? World
Handler: xmlcharrefreplace: Hello – World
Handler: namereplace: Hello \N{EN DASH} World

Обработчики игнорируют и replace теряют информацию - вы не можете сказать, какой символ был заменен пробелом или вопросительным знаком.

* 1076Обработчики * xmlcharrefreplace и namereplace не теряют информацию, но последовательности замены могут сделать текст менее читабельным для людей.

Вам решать, какой компромисс приемлем дляпотребители вывода вашей программы.

Если вы решили использовать обработчик replace , вы бы изменили свой код следующим образом:

for i in patchlets_in_latest_list:
    replaced = i.encode('ascii', errors='replace').decode('ascii')
    print(replaced)

везде, где вы печатаете данные, которые могут содержать символы не ASCII.

...