为什么我在格式字符串的python warnings.formatwarning中遇到编码错误?

5 python encoding warnings

我在这一行得到编码错误:

s =  "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
Run Code Online (Sandbox Code Playgroud)

UnicodeEncodeError:'ascii'编解码器不能编码位置44中的字符u'\ xc4':序数不在范围内(128)

我尝试通过将所有参数组合传递给字符串格式来重现此错误,但最接近的是"ascii decode"错误(通过同时传递unicode和高ascii字符串,强制使用ascii解码器将字符串转换为unicode.

但是,我没有设法得到"ascii编码"错误.有人有想法吗?

Aar*_*lla 8

当Python试图强制参数时会发生这种情况:

s = u"\u00fc"
print str(s)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 0: ordinal not in range(128)
Run Code Online (Sandbox Code Playgroud)

发生这种情况是因为你的一个参数是一个对象(不是任何类型的字符串)和Python调用str()它.有两种解决方案:对format(s = u"%s...")使用unicode字符串或用每个参数包装repr().


Len*_*bro 8

你正在混合unicode和str对象.

说明:在Python 2.x中,有两种对象可以包含文本字符串.str和unicode.str是一个字节字符串,因此它只能包含0到255之间的字符.Unicode是一串unicode字符.

您可以使用"encode"和"decode"方法在str和unicode之间进行转换:

>>> "thisisastring".decode('ascii')
u'thisisastring'

>>> u"This is ä string".encode('utf8')    
'This is \xc3\xa4 string'
Run Code Online (Sandbox Code Playgroud)

注意编码.编码是将unicode文本表示为仅字节串的方式.

如果您尝试将str和unicode一起添加,Python将尝试将一个转换为另一个.但默认情况下它会使用ASCII作为编码,这意味着az,AZ和一些额外的字符等!"#$%&/()=?'{[]]}.其他任何东西都会失败.

您将在此时获得编码错误或解码错误,具体取决于Python是否尝试将unicode转换为str或str转换为unicode.通常它会尝试解码,即转换为unicode.但有时它决定不要强迫串起来.我不完全确定为什么.

更新:您获得编码错误而不是上面的解码错误的原因是message上面的代码既不是str也不是unicode.这是另一个有str方法的对象.因此,Python在传入之前执行str(message),并且失败,因为内部存储消息是一个无法强制转换为ascii的unicode对象.

或者,更简单地回答:它失败,因为warnings.warn()不接受unicode消息.

现在,解决方案:

不要混合str和unicode.如果你需要使用unicode,而你显然是这样做,请尝试确保所有字符串始终是unicode.这是确保你避免这种情况的唯一方法.这意味着无论何时从磁盘读取字符串,或者调用可能返回除纯ascii str以外的任何内容的函数,请尽快将其解码为unicode.当您需要将其保存到磁盘或通过网络发送或将其传递给不理解unicode的方法时,请尽可能晚地将其编码为str.

在这种特定情况下,问题是您将unicode传递给warnings.warn()而您无法执行此操作.传递一个字符串.如果你不知道它是什么(这里似乎是这种情况),因为它来自其他地方,你的try/except解决方案与repr工作正常,虽然做一个编码是可能的.

  • 我认为提问者完全清楚问题是unicode和str在某种程度上是混合的; 问题是为什么在通常应该将输出强制转换为unicode的操作上触发此错误. (2认同)