tl;dr / quick fix
- 不要对Willy Nilly进行解码/编码
- 不要以为你的字符串是UTF-8编码的
- 尝试在代码中尽快将字符串转换为Unipre字符串
- 解决你的语言环境:如何在Python 3.6中解决UnipreDepreError?
- 不要试图使用快速reloadhack
Python 2.x中的Unipre Zen-完整版
在没有看到来源的情况下,很难知道根本原因,因此我将不得不大体讲一下。
UnipreDepreError: 'ascii' prec can't depre byte当你尝试将str包含非ASCII 的Python 2.x转换为Unipre字符串而不指定原始字符串的编码时,通常会发生这种情况。
简而言之,Unipre字符串是一种完全独立的Python字符串类型,不包含任何编码。它们仅保存Unipre 点代码,因此可以保存整个频谱中的任何Unipre点。字符串包含编码的文本,如UTF-8,UTF-16,ISO-8895-1,GBK,Big5等。字符串被解码为Unipre,而Unipres被编码为字符串。文件和文本数据始终以编码的字符串传输。
Markdown模块的作者可能会使用unipre()(抛出异常的地方)作为其余代码的质量门-它会转换ASCII或将现有的Unipre字符串重新包装为新的Unipre字符串。Markdown作者无法得知传入字符串的编码,因此在传递给Markdown之前,将依赖你将字符串解码为Unipre字符串。
可以使用u字符串的前缀在代码中声明Unipre 字符串。例如
>>> my_u = u'my ünicôdé strįng'>>> type(my_u)<type 'unipre'>
Unipre字符串也可能来自文件,数据库和网络模块。发生这种情况时,你无需担心编码。
Gotchas
str即使不显式调用,也可能会发生从
Unipre到
Unipre的转换
unipre()。
以下情况导致
UnipreDepreError异常:
# Explicit conversion without encodingunipre('€')# New style format string into Unipre string# Python will try to convert value string to Unipre firstu"The currency is: {}".format('€')# Old style format string into Unipre string# Python will try to convert value string to Unipre firstu'The currency is: %s' % '€'# Append string to Unipre# Python will try to convert string to Unipre firstu'The currency is: ' + '€'
例子
在下图中,你可以看到如何café根据终端类型以“ UTF-8”或“ Cp1252”编码方式对单词进行编码。在两个示例中,caf都是常规的ascii。在UTF-8中,é使用两个字节进行编码。在“ Cp1252”中,é是0xE9(它也恰好是Unipre点值(这不是巧合))。正确的depre()被调用,并成功转换为Python Unipre: 将字符串转换为Python Unipre字符串的图
在此图中,使用
depre()进行调用
ascii(与
unipre()没有给出编码的调用相同)。由于ASCII不能包含大于的字节
0x7F,这将引发
UnipreDepreError异常:
将字符串转换为编码错误的Python Unipre字符串的图
The Unipre Sandwich
最好在代码中形成一个Unipre三明治,在该代码中,你将所有传入数据解码为Unipre字符串,使用Unipre,然后在输出时编码为strs。这使你不必担心代码中间的字符串编码。
输入/解码
源代码
如果你需要将非ASCII烘烤到源代码中,只需通过在字符串前面加上来创建Unipre字符串u。例如
u'Zürich'
为了允许Python解码你的源代码,你将需要添加一个编码标头以匹配文件的实际编码。例如,如果你的文件编码为“ UTF-8”,则可以使用:
# encoding: utf-8
仅当源代码中包含非ASCII时才需要这样做。
档案
通常从文件接收非ASCII数据。该io模块提供了一个TextWrapper,它使用给定即时解码文件encoding。你必须为文件使用正确的编码-不容易猜测。例如,对于UTF-8文件:
import iowith io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file: my_unipre_string = my_file.read()
my_unipre_string然后适合传递给Markdown。如果
UnipreDepreError从read()行开始,则你可能使用了错误的编码值。
CSV文件
Python 2.7 CSV模块不支持非ASCII字符。但是,https://pypi.python.org/pypi/backports.csv提供了帮助。
像上面一样使用它,但是将打开的文件传递给它:
from backports import csvimport iowith io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file: for row in csv.reader(my_file): yield row
资料库
大多数Python数据库驱动程序都可以Unipre格式返回数据,但是通常需要一些配置。始终对SQL查询使用Unipre字符串。
MySQL
在连接字符串中添加:
charset='utf8',use_unipre=True
例如
>>> db = MySQLdb.connect(host="localhost", user='root', passwd='passwd', db='sandbox', use_unipre=True, charset="utf8")PostgreSQL
加:
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
HTTP
网页几乎可以采用任何编码方式进行编码。的Content-type报头应包含一个charset字段在编码暗示。然后可以根据该值手动解码内容。另外,Python-Requests在中返回Unipre response.text。
Manually
如果必须手动解码字符串,则可以简单地执行my_string.depre(encoding),其中encoding是适当的编码。此处提供了Python 2.x支持的编解码器:标准编码。同样,如果你得到了,UnipreDepreError则可能是编码错误。
The meat of the sandwich
像正常strs一样使用
Unicode。
Output
stdout / printing
print通过stdout流写入。Python尝试在stdout上配置编码器,以便将Unipre编码为控制台的编码。例如,如果
Linux shell locale是
en_GB.UTF-8,则输出将被编码为
UTF-8。在Windows上,你将被限制为8位代码页。
错误配置的控制台(例如损坏的语言环境)可能导致意外的打印错误。PYTHONIOENCODING环境变量可以强制对stdout进行编码。
档案
就像输入一样,
io.open可用于将
Unipre透明地转换为编码的字节字符串。
数据库
用于读取的相同配置将允许直接编写
Unipre。
Python 3
Python 3不再比Python 2.x更具有Unipre功能,但是在该主题上的混淆却稍少一些。例如,常规str字符串现在是Unipre字符串,而旧字符串str现在是bytes。
默认编码为UTF-8,因此,如果你.depre()未提供任何编码的字节字符串,Python 3将使用UTF-8编码。这可能解决了50%的人们的Unipre问题。
此外,open()默认情况下以文本模式运行,因此返回已解码str(Unipre 编码)。编码来自你的语言环境,在Un * x系统上通常是UTF-8,在Windows机器上通常是8位代码页,例如Windows-1251。
为什么不应该使用
sys.setdefaultencoding('utf8')
这是一个令人讨厌的hack(有必要使用reload),它只会掩盖问题并阻碍你迁移到Python3.x。理解问题,解决根本原因并享受
Unipre zen。请参阅为什么我们不应该在py脚本中使用
sys.setdefaultencoding(“ utf-8”)?了解更多详情
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)