UnicodeEncodeError: 'ascii' 编解码器无法在打印功能中编码字符

rik*_*kki 4 python ascii character-encoding python-3.x

我的公司正在使用一个数据库,我正在编写一个与该数据库交互的脚本。已经有一个脚本用于将查询放在数据库上,并基于该脚本将从数据库返回结果的查询。

我正在 unix 环境中工作,我在脚本中使用该脚本从数据库中获取一些数据,并将查询结果重定向到文件。现在,当我尝试读取此文件时,我收到一条错误消息:

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

我知道由于文件的编码,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))))
Run Code Online (Sandbox Code Playgroud)

其中 Query.pl 是为从数据库中引入查询结果而编写的 perl 脚本。我为“patchlet.txt”(用于存储来自 HSD 的结果的文件)获得的编码是:

{'encoding': 'Windows-1252', 'confidence': 0.73, 'language': ''}
Run Code Online (Sandbox Code Playgroud)

即使我为读取文件提供了相同的编码,我也会收到错误消息。

请帮助我解决此错误。

编辑: 我正在使用 python3.6

编辑2:

在输出结果时,我收到错误消息,文件中有一行包含一些未知字符。该行看起来像:

一些失败,因为 vtrace 不能与一些跟踪一起使用。

我正在使用 gvim,在 gvim 中,“vtrace”看起来像“~Vvtrace”。然后我手动检查了数据库中的这个字符,字符是“-”,根据我的键盘,它既不是连字符也不是下划线。这些类型的字符造成了问题。

我也在 linux 环境中工作。

编辑 3: 我添加了更多有助于跟踪错误的代码。此外,我还突出显示了(print(str(i)))出现错误的“打印”语句。

sna*_*erb 5

问题

根据问题中的信息,程序正在处理非 ASCII 输入数据,但无法输出非 ASCII 数据。

具体来说,这段代码:

for i in patchlets_in_latest_list:
   print(str(i))
Run Code Online (Sandbox Code Playgroud)

导致此异常:

UnicodeEncodeError: 'ascii' 编解码器无法编码字符 '\u2013'

这种行为在Python2,其中调用是常见的str一对unicode对象会导致Python来尝试将对象编码为ASCII,导致UnicodeEncodeError如果对象包含非ASCII字符。

在Python3,要求strstr实例不会触发任何编码。但是,print在 a 上调用该函数str将对strto进行编码sys.stdout.encodingsys.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 编码 - 除非明确设置了语言环境。同样,如果脚本在不同的用户下运行,请检查他们的区域设置。

解决方法

如果更改环境不可行,您可以通过使用错误处理程序编码为 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
Run Code Online (Sandbox Code Playgroud)

忽略更换处理器丢失信息-你不能告诉字符被替换为空格或问号。

xmlcharrefreplacenamereplace处理程序不丢失信息,但更换序列可以使文本的可读性于人类。

由您决定哪种权衡对于您的程序输出的使用者来说是可以接受的。

如果您决定使用替换处理程序,您可以像这样更改代码:

for i in patchlets_in_latest_list:
    replaced = i.encode('ascii', errors='replace').decode('ascii')
    print(replaced)
Run Code Online (Sandbox Code Playgroud)

无论您在哪里打印可能包含非 ASCII 字符的数据。


归档时间:

查看次数:

5304 次

最近记录:

7 年,3 月 前