UnicodeEncodeError:“ ascii”编解码器无法对打印功能中的字符进行编码

时间:2019-02-04 08:26:51

标签: python python-3.x character-encoding ascii

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

我在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

EDIT2:

在输出结果时,我得到了错误,并且文件中有一行包含一些未知字符。该行如下所示:

  

由于某些vtrace无法与某些跟踪一起使用而导致的某些故障。

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

我也在Linux环境下工作。

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

1 个答案:

答案 0 :(得分:1)

问题

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

具体来说,这段代码:

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

导致此异常的结果:

  

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

此行为在Python2中很常见,在str对象上调用unicode会使Python尝试将对象编码为ASCII,如果对象包含非-ASCII字符。

在Python3中,在UnicodeEncodeError实例上调用str不会触发任何编码。但是,在str上调用print函数会将str编码为strsys.stdout.encoding默认为locale.getpreferredencoding返回的值。通常,这将是您的Linux用户的sys.stdout.encoding环境变量。

解决方案

如果我们假设您的程序未取代正常的编码行为,则应通过确保代码由UTF-8语言环境中的Python3解释器执行来解决此问题。

  • 100%,确保代码正在由Python3解释器执行-从程序中的打印LANG
  • 在运行脚本时尝试设置PYTHONIOENCODING环境变量:sys.version_info
  • 使用终端中的PYTHONIOENCODING=UTF-8 python3 myscript.py命令(或locale)检查您的语言环境。如果它的结尾不是echo $LANG,请考虑对其进行更改。如果您在公司计算机上,请咨询系统管理员。
  • 如果您的代码在cron作业中运行,请记住,除非明确设置了语言环境,否则cron作业通常以'C'或'POSIX'语言环境(可能使用ASCII编码)运行。同样,如果脚本在其他用户下运行,请检查其区域设置。

解决方法

如果更改环境不可行,则可以通过使用错误处理程序编码为ASCII,然后解码回UTF-8来解决Python中的问题。

在您的特定情况下有四个有用的错误处理程序,它们的效果通过以下代码演示:

str

ignore replace 处理程序会丢失信息-您无法确定空格或问号已替换了哪个字符。

xmlcharrefreplace namereplace 处理程序不会丢失信息,但是替换序列可能会使文本对人类的可读性降低。

由您决定哪种折衷方案对于程序输出的使用者是可接受的。

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

>>> 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

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