我的公司正在使用数据库,而我正在编写与该数据库交互的脚本。已经存在用于将查询放在数据库中的脚本,并且基于查询,该脚本将从数据库返回结果。
我在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)))
,该错误在哪里出现。
答案 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
编码为str
。 sys.stdout.encoding
默认为locale.getpreferredencoding返回的值。通常,这将是您的Linux用户的sys.stdout.encoding
环境变量。
解决方案
如果我们假设您的程序未取代正常的编码行为,则应通过确保代码由UTF-8语言环境中的Python3解释器执行来解决此问题。
LANG
。sys.version_info
PYTHONIOENCODING=UTF-8 python3 myscript.py
命令(或locale
)检查您的语言环境。如果它的结尾不是echo $LANG
,请考虑对其进行更改。如果您在公司计算机上,请咨询系统管理员。解决方法
如果更改环境不可行,则可以通过使用错误处理程序编码为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字符的数据。