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)))出现错误的“打印”语句。
问题
根据问题中的信息,程序正在处理非 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,要求str在str实例不会触发任何编码。但是,print在 a 上调用该函数str将对strto进行编码sys.stdout.encoding。 sys.stdout.encoding默认为locale.getpreferredencoding返回的值。这通常是您的 linux 用户的LANG环境变量。
解决方案
如果我们假设您的程序没有覆盖正常的编码行为,那么应该通过确保代码由 Python3 解释器在 UTF-8 语言环境中执行来解决问题。
sys.version_info从程序内。PYTHONIOENCODING=UTF-8 python3 myscript.pylocale终端(或echo $LANG)中的命令检查您的语言环境。如果它不是以 结尾UTF-8,请考虑更改它。如果您使用的是公司计算机,请咨询您的系统管理员。解决方法
如果更改环境不可行,您可以通过使用错误处理程序编码为 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)
在忽略和更换处理器丢失信息-你不能告诉字符被替换为空格或问号。
该xmlcharrefreplace和namereplace处理程序不丢失信息,但更换序列可以使文本的可读性于人类。
由您决定哪种权衡对于您的程序输出的使用者来说是可以接受的。
如果您决定使用替换处理程序,您可以像这样更改代码:
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 次 |
| 最近记录: |