【问题标题】:python 3.2 UnicodeEncodeError: 'charmap' codec can't encode character '\u2013' in position 9629: character maps to <undefined>python 3.2 UnicodeEncodeError:“charmap”编解码器无法在位置 9629 编码字符“\u2013”​​:字符映射到 <undefined>
【发布时间】:2013-05-02 20:13:49
【问题描述】:

我正在尝试制作一个从 sqlite3 数据库中获取数据的脚本,但我遇到了问题。

数据库中的字段是文本类型,并且包含 html 格式的文本。见下文

<html>
<head>
<title>Yahoo!</title>
</head>
<body>
<style type="text/css">
html {}
.yshortcuts {border-bottom:none !important;}
.ReadMsgBody {width:100%;}
.ExternalClass{width:100%;}
</style>
<table cellpadding="0" cellspacing="0" bgcolor="#ffffff">    
<tr>
<td width="550" valign="top" align="left">

    <table cellpadding="0" cellspacing="0" width="500">
        <tr>
            <td colspan="3"><img        src="http://mail.yimg.com/nq/assets/sharedmessages/v1/us/logo.gif" width="292" height="51" style="display:block;" border="0" alt="Yahoo! Mail"></td>
        </tr>
        <tr>
            <td rowspan="3" width="1" bgcolor="#c7c4ca"></td>
            <td width="498" height="1" bgcolor="#c7c4ca"></td>
            <td rowspan="3" width="1" bgcolor="#c7c4ca"></td>
        </tr>
        <tr>
            <td width="498" valign="top" align="left">
            <table cellpadding="0" cellspacing="0">
                <tr>
                    <td width="498" bgcolor="#61399d" align="left" valign="top">
                    <table cellspacing="0" cellpadding="0"><tr><td height="24"></td></tr></table>
                    <div style="font-family:Arial, Helvetica, sans-serif;font-size:23px;line-height:27px;margin-bottom:10px;color:#ffffff;margin-left:15px;"><span style="color:#ffffff;text-decoration:none;font-weight:bold;line-height:27px;">Välkommen till Yahoo! Mail.</span></div>
                    <div style="font-family:Arial, Helvetica, sans-serif;font-size:22px;line-height:26px;margin-bottom:1px;color:#ffffff;margin-left:15px;margin-bottom:7px;margin-right:15px;">Ansluta och dela går snabbt och enkelt och är tillgängligt överallt.</div>
                    </td>
                </tr>
                <tr>
                    <td><img src="http://mail.yimg.com/nq/assets/sharedmessages/v1/all/b1.gif" width="498" height="18" style="display:block;" border="0"></td>
                </tr>
            </table>
            <table cellpadding="0" cellspacing="0" width="498">
                <tr>
                    <td width="292" valign="top">
                    <table cellpadding="0" cellspacing="0">
                        <tr>
                            <td><img src="http://mail.yimg.com/nq/assets/sharedmessages/v1/all/grad.gif" width="292" height="9" style="display:block;"></td>
                        </tr>
                        <tr>
                            <td width="292" bgcolor="#ffffff" align="left" valign="top">
                            <table cellspacing="0" cellpadding="0"><tr><td height="11"></td></tr></table>
                            <div style="margin-left:15px;">                  
                                <div style="font-family:Arial, Helvetica, sans-serif;font-size:14px;line-height:18px;color:#333333;margin-bottom:11px;font-weight:bold;">Det är lätt som en plätt att komma igång.</div>
                                <table cellpadding="0" cellspacing="0" width="267">
                                    <tr>
                                        <td width="16" align="left" valign="top"><div style="font-family:Arial, Helvetica, sans-serif;font-size:14px;line-height:16px;color:#61399d;margin-bottom:9px;font-weight:bold;">1. </div></td>
                                        <td align="left" valign="top"><div style="font-family:Arial, Helvetica, sans-serif;font-size:13px;line-height:16px;color:#61399d;margin-bottom:9px;"><a rel="nofollow" target="_blank" href="http://us-mg999.mail.yahoo.com/neo/launch?action=contacts" style="text-decoration:underline;color:#61399d;"><span>Lägg till alla dina kontakter på en plats</span></a>.</div></td>
                                    </tr>
                                    <tr>
                                        <td align="left" valign="top"><div style="font-family:Arial, Helvetica, sans-serif;font-size:14px;line-height:16px;color:#61399d;margin-bottom:9px;font-weight:bold;">2. </div></td>
                                        <td align="left" valign="top"><div style="font-family:Arial, Helvetica, sans-serif;font-size:13px;line-height:16px;color:#61399d;margin-bottom:9px;"><a rel="nofollow" target="_blank" href="http://mrd.mail.yahoo.com/themes" style="text-decoration:underline;color:#61399d;"><span>Anpassa din nya inkorg</span></a>.</div></td>
                                    </tr>
                                    <tr>
                                        <td align="left" valign="top"><div style="font-family:Arial, Helvetica, sans-serif;font-size:14px;line-height:16px;color:#61399d;margin-bottom:9px;font-weight:bold;">3. </div></td>
                                        <td align="left" valign="top"><div style="font-family:Arial, Helvetica, sans-serif;font-size:13px;line-height:16px;color:#61399d;"><a rel="nofollow" target="_blank" href="http://se.overview.mail.yahoo.com/mobile" style="text-decoration:underline;color:#61399d;"><span>Anslut överallt på dina mobila enheter</span></a>.</div></td>
                                    </tr>
                                </table>

                            </div>
                            </td>
                        </tr>
                        <tr><td height="13"></td></tr>
                    </table>
                    </td>
                    <td width="196" valign="top">
                    <table cellpadding="0" cellspacing="0">
                        <tr>
                            <td width="1" bgcolor="#fbfbfd" valign="top"><img src="http://mail.yimg.com/nq/assets/sharedmessages/v1/all/g1.gif" width="1" height="21" style="display:block;"></td>
                            <td width="1" bgcolor="#f5f6fa" valign="top"><img src="http://mail.yimg.com/nq/assets/sharedmessages/v1/all/g2.gif" width="1" height="21" style="display:block;"></td>
                            <td width="1" bgcolor="#e8eaf1" valign="top"><img src="http://mail.yimg.com/nq/assets/sharedmessages/v1/all/g3.gif" width="1" height="21" style="display:block;"></td>
                            <td width="1" bgcolor="#d4d4d4"></td>
                            <td width="186" bgcolor="#f0f0f0" align="left" valign="top">  
                            <table cellspacing="0" cellpadding="0"><tr><td height="3">   </td></tr></table>
                            <div style="margin-left:11px;">
                            <div style="font-family:Arial, Helvetica, sans-serif;font-size:13px;line-height:16px;color:#333333;margin-bottom:9px;"><b>Info för dig:</b></div>
                            <div style="font-family:Arial, Helvetica, sans-serif;font-size:12px;color:#43494e;line-height:18px;margin-bottom:10px;">
                            Yahoo!-ID och e-postadress:<br />
                            <div style="font-family:Arial, Helvetica, sans-serif;font-size:12px;color:#43494e;line-height:18px;">
                            Håll ditt konto och inställningar aktuella. <br><a rel="nofollow" target="_blank" href="https://edit.yahoo.com/config/eval_profile" style="text-decoration:underline;color:#61399d;"><span>Mitt konto</span></a> 
                            </div>
                            </div>
                            <table cellspacing="0" cellpadding="0"><tr><td height="20"></td></tr></table>
                            </td>
                            <td width="1" bgcolor="#dbdbdb"></td>
                            <td width="1" bgcolor="#ced2de"></td>
                            <td width="1" bgcolor="#dbdfed"></td>
                            <td width="1" bgcolor="#e8ebf3"></td>
                            <td width="1" bgcolor="#f3f4f9"></td>
                            <td width="1" bgcolor="#fafbfc"></td>
                        </tr>
                        <tr>
                            <td colspan="11"><img src="http://mail.yimg.com/nq/assets/sharedmessages/v1/all/b2.gif" width="196" height="8" style="display:block;" border="0"></td>
                        </tr>
                        <tr><td height="13"></td></tr>
                    </table>
                    </td>
                    <td width="10"></td>
                </tr>
            </table>
            </td>
        </tr>
        <tr>
            <td width="498" height="1" bgcolor="#c7c4ca"></td>
        </tr>
    </table>
    <table cellpadding="0" cellspacing="0" width="500">
        <tr>
            <td align="center" valign="top">
            <table cellspacing="0" cellpadding="0"><tr><td height="10"></td></tr></table>
                <div style="font-family:Arial, Helvetica, sans-serif;font-size:11px;line-height:18px;margin-bottom:10px;">
                <a rel="nofollow" target="_blank" href="http://info.yahoo.com/legal/se/yahoo/utos.html" style="text-decoration:underline;color:#61399d;">Yahoo! Villkor för användning</a>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;<a rel="nofollow" target="_blank" href="http://info.yahoo.com/legal/se/yahoo/mail/atos.html" style="text-decoration:underline;color:#61399d;">Yahoo! Mail –Villkor för användning</a>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;<a rel="nofollow" target="_blank" href="http://info.yahoo.com/privacy/se/yahoo/details.html" style="text-decoration:underline;color:#61399d;">Yahoo! Sekretesspolicy</a>
                </div>
            </td>
        </tr>
        <tr>
            <td align="left" valign="top">
                <div style="font-family:Arial, Helvetica, sans-serif;font-size:11px;line-height:14px;color:#545454;margin-left:16px;margin-right:14px;">Var god svara inte på detta meddelande. Detta är ett servicemeddelande som rör din användning av Yahoo! Mail. Om du vill veta mer om Yahoo!s användning av personlig information, inklusive användning av webb-beacons i HTML-baserad e-post, kan du läsa vår Yahoo! Sekretesspolicy. Yahoo!s adress är 701 First Avenue, Sunnyvale, CA 94089, USA.<br /><br />RefID: lp-1037111</div>
            </td>
        </tr>
    </table>





    </td>
</tr>
</table>
<img width="1" height="1" src="http://pclick.internal.yahoo.com/p/s=2143684696">
</body>
</html>`

尝试提取数据的python代码如下。

>>> import sqlite3
>>> conn = sqlite3.connect('C:/temp/Mobils/export/com.yahoo.mobile.client.android.mail/databases/mail.db')
>>> c = conn.cursor()
>>> conn.row_factory=sqlite3.Row
>>> c.execute('select body from messages_1 where _id=7')
<sqlite3.Cursor object at 0x0000000001FB78F0>
>>> r = c.fetchone()
>>> r.keys()
['body']
>>> print(r['body'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python32\lib\encodings\cp850.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_map)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u2013' in position 9629: character maps to <undefined>
>>>

是否有人知道如何将其打印/写入文件。是的,我知道这是打印到标准输出的,但是当我尝试写入文件时,我得到了相同的 UnicodeEncodeError。我尝试了文件对象的写入方法和print(r['body'], file=f)

【问题讨论】:

  • 这是一个 Windows 控制台问题,请参阅wiki.python.org/moin/PrintFails
  • 写入文件时,选择可以处理数据中代码点的编解码器。最好阅读 Python 和 Unicode:Python Unicode HOWTO.
  • 打印前一个简单的replace("\u2013", "-") 对我有用。 P.S.:是不是很好笑? 2013年问了一个关于字符代码\u2013问题的问题。

标签: python python-3.x sqlite


【解决方案1】:

当您打开要写入的文件时,使用可以处理所有字符的特定编码打开它。

with open('filename', 'w', encoding='utf-8') as f:
    print(r['body'], file=f)

【讨论】:

  • 这解决了一半的问题,打印到一个文件。它没有解决另一半,打印到stdout,它连接到一个cp850 Windows控制台。
  • 这有点奏效。它现在将数据库内容打印到文件中,但每个字符都在新行上,这会导致浏览器无法解释文件。
  • @abarnert 当您在 2013 年撰写评论时,此解决方案不可用,但现在您可以使用 Python 3.6 或更高版本。它绕过控制台 I/O 以支持真正的 Unicode。
【解决方案2】:

对我来说,在执行 python 命令之前使用 export PYTHONIOENCODING=UTF-8 有效。

【讨论】:

  • 这对于 Azure Pipelines 也非常有用,您可以在 PythonScript 任务上设置它。
【解决方案3】:

虽然 Python 3 处理 Unicode,但您在其中运行的 Windows 控制台或 POSIX tty 不处理。因此,无论何时您 print,或以其他方式将 Unicode 字符串发送到 stdout,并且它附加到控制台/tty,Python 都必须对其进行编码。

错误信息间接告诉你 Python 试图使用什么字符集:

  File "C:\Python32\lib\encodings\cp850.py", line 19, in encode

这意味着字符集是cp850

您可以通过执行'\u2013'.encode('cp850') 来测试此字符集是否不包含适当的字符。或者您可以在线查找 cp850(例如,Wikipedia)。

Python 可能猜错了,而您的控制台确实设置为 UTF-8。 (在这种情况下,只需手动设置 sys.stdout.encoding='utf-8'。)您也可能打算将控制台设置为 UTF-8,但做错了。 (在这种情况下,您可能需要在 superuser.com 上跟进。)

但如果没有问题,您就无法打印该字符。您将不得不使用非严格的错误处理程序之一对其进行手动编码。例如:

>>> '\u2013'.encode('cp850')
UnicodeEncodeError: 'charmap' codec can't encode character '\u2013' in position 0: character maps to <undefined>
>>> '\u2013'.encode('cp850', errors='replace')
b'?'

那么,如何打印不会在控制台上打印的字符串?

可以将每个 print 函数替换为以下内容:

>>> print(r['body'].encode('cp850', errors='replace').decode('cp850'))
?

……但这很快就会变得相当乏味。

简单的做法是在sys.stdout 上设置错误处理程序:

>>> sys.stdout.errors = 'replace'
>>> print(r['body'])
?

对于打印到文件,事情几乎相同,只是您不必在事后设置f.errors,您可以在构建时设置它。而不是这个:

with open('path', 'w', encoding='cp850') as f:

这样做:

with open('path', 'w', encoding='cp850', errors='replace') as f:

... 或者,当然,如果您可以使用 UTF-8 文件,就这样做,正如 Mark Ransom 的回答所示:

with open('path', 'w', encoding='utf-8') as f:

【讨论】:

  • 我尝试了您的建议,但错误消失了,但文件中的文本每行打印一个字符,导致浏览器无法正确解释文件。关于如何纠正或为什么会发生这种情况的任何想法?我说我的错误中使用了cp1252.py文件所以我将编码改为cp1252而不是cp850,但原理应该是一样的吧?
  • @Mattias:是的,对于没有完全覆盖 Unicode 的任何编解码器(基本上,除了 utf-8 和 utf-7 之外的所有编解码器),原理都是相同的。如果您在实际使用中使用了 cp1252,我很好奇您是如何在粘贴到此处的错误中得到 cp850 的。您是从哪里复制并粘贴该错误的?
  • @Mattias:同时......每行获取一个字符的最常见原因是将字符串视为代码中某处的字符串序列。 (字符串 1 个字符的字符串序列,所以它可以工作,但不是您希望的方式。)但是我们必须实际查看相关代码来帮助您调试它。几乎可以肯定,这与这个问题完全不同,因此您可能应该创建一个新问题。
  • @Mattias:举个例子来说明如何解决这个每行一个字符的问题……如果你先做bodies = [row['body'] for row in c.fetchall()] 然后for body in bodies: print(body),那是正确的。但是如果你先bodies = c.fetchone()['body'] 然后for body in bodies: print(body),它会一次给你一个字符。
  • 我在控制台中编写的更小的示例代码中重新创建问题时收到了错误消息。
【解决方案4】:

在 Windows 上(git bash):

chcp.com 65001
export PYTHONIOENCODING=utf-8

然后你可以运行你的脚本,在我的例子中它是烧瓶,所以最后它可以在我的网站上从 mysql db 解码 utf...

【讨论】:

    【解决方案5】:

    回复可能有点晚了。我今天碰巧遇到了同样的问题。我发现在 Windows 上,您可以将控制台编码器更改为 utf-8 或其他可以代表您的数据的编码器。然后可以打印到sys.stdout

    首先,在控制台中运行以下代码:

    chcp 65001
    set PYTHONIOENCODING=utf-8
    

    然后,开始python 做任何你想做的事情。

    【讨论】:

    • 有没有办法在脚本的开头设置这个?
    • @dreyco676 我不知道。看看这个,可能会有所帮助stackoverflow.com/questions/492483/…
    • 这解决了我在 Windows 上的问题。由于我使用了 ConEmu 和 git-bash 的组合,因此解决方案是以这种形式将这些命令添加到我的 ~/.basrhc 中:export ConEmuDefaultCp=65001export PYTHONIOENCODING=utf-8。在 git-bash 中,您需要使用 export 代替 set,并且使用 ConEmu,环境变量 ConEmuDefaultCP 在此答案中的功能类似于 chcp
    • Fabric 和 pip install -command 有类似的问题。我在 Windows PowerShell 上运行 fab deploy,这确实成功了。谢谢!
    • 从 Python 3.6 开始,不再需要使用 chcp 命令在控制台中获得完整的 Unicode 支持,请参阅 PEP 528。如果在将输出重定向到文件时需要 UTF-8,PYTHONIOENCODING 可能仍然是必需的。
    猜你喜欢
    • 1970-01-01
    • 2018-07-30
    • 2021-01-27
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 2022-06-11
    • 2018-09-15
    • 2013-02-17
    相关资源
    最近更新 更多