Python解码对我有效,但对其他人无效

Python解码对我有效,但对其他人无效,python,encoding,character-encoding,Python,Encoding,Character Encoding,我确信这个问题已经在某处得到了回答,但我不知道该寻找什么。我的问题与其说是我的问题,不如说是其他人的问题。长话短说,我有一个带有文本解码的Python脚本,它对我来说解码很好,但对其他用户来说却失败了,即使使用相同的代码和输入 ()通过将PIM备份内容转换为SMSB&R兼容的XML格式,将Windows Mobile 6 SMSE(通过输出)转换为Android SMSE(通过输入) 现在,PIM备份以UCS-2 Little Endian格式输出其内容,这很好,因为它支持各种国际对话。在我的脚

我确信这个问题已经在某处得到了回答,但我不知道该寻找什么。我的问题与其说是我的问题,不如说是其他人的问题。长话短说,我有一个带有文本解码的Python脚本,它对我来说解码很好,但对其他用户来说却失败了,即使使用相同的代码和输入

()通过将PIM备份内容转换为SMSB&R兼容的XML格式,将Windows Mobile 6 SMSE(通过输出)转换为Android SMSE(通过输入)

现在,PIM备份以UCS-2 Little Endian格式输出其内容,这很好,因为它支持各种国际对话。在我的脚本中,我使用Python内置的字符串解码加载内容,并使用以下内容创建csv阅读器对象:

# Read the file contents
sms_text = csv_file.read().decode('utf-16').split(os.linesep)
sms_reader = csv.reader(sms_text, delimiter=';', quotechar='"', escapechar='\\')
然后,我用以下方法处理csv读取器的每一行:

row = sms_reader.next()
我把它放在
try
块中,因为它偶尔会在出现问题时抛出
UnicodeEncodeError
。但是,这对我来说是非常罕见的

我的问题是,对于在SMSE中使用非ASCII字符的脚本的其他用户来说,这似乎总是被抛出。最近,一位德国用户联系我说,他的SMSE只有10%的解码正确。他向我发送了他的.pib文件,我通过脚本运行了它,在转换过程中没有任何问题。所有的输出似乎都是标准的ANSI/ISO8859-1/Windows-1252/等等,所以几乎没有异国情调

我的问题是,为什么在我没有问题的情况下,这些用户无法使用完全相同的代码(以及Python版本)解码他们的输入?作为后续行动,我能做些什么来修改我的剧本,使它适合所有人

编辑:我没有提到的一个要点是,我正在使用PyDev在Eclipse中运行脚本。当我在命令提示符下运行它时,它会抛出与其他所有人相同的问题!我仍然不知道问题是什么,但希望这有助于缩小范围

具有非标准字符的非常简单的.csm文件(从.pib文件中提取,名称和数字已更改)示例如下:

Msg Id;Sender Name;Sender Address;Sender AddressType;Prefix;Subject;Body;BodyType;Folder;Account;Msg Class;Content Length;Msg Size;Msg Flags;Msg Status;Modify Time;Delivery Time;Recipient Nbr;Recipients;Attachment Nbr;Attachments
0x00,0x00;"491703000000";"491703000000";;"";"Wir wünschen dem rainer alles gute und viel gesundheit! Bis nächste woche, wir hören uns bis dahin noch mal.. Liebe grüße aus md!";"";0;"\\%MDF3";"SMS";"IPM.SMStext";;;33;262144;2007,09,23,19,44,32;2007,09,23,19,44,31;1;"851980\;Gela\;+491739000000\;1\;0\;SMS";0;""
Msg Id;Sender Name;Sender Address;Sender AddressType;Prefix;Subject;Body;BodyType;Folder;Account;Msg Class;Content Length;Msg Size;Msg Flags;Msg Status;Modify Time;Delivery Time;Recipient Nbr;Recipients;Attachment Nbr;Attachments
0x00,0x00;"Jonas/M";"\"Jonas/M\" <+46737000000>";;"";"Den går 28 ";"";2;"\\%MDF4";"SMS";"IPM.SMStext";0;24;0;0;2011,03,12,21,15,19;2011,03,12,21,16,17;0;"";0;""
0x00,0x00;"Don Vär";"\"Don Vär\" <+46709000000>";;"";"försöke® dhdjhdhhdjehdejehţýùhbfvfghjujhuikjkłánjajnxsjajmsxnsmajmkjsnshdjnsjmwkjhdnjsjmwkjdhjjdewjjwjwjw®";"";2;"\\%MDF1";"SMS";"IPM.SMStext";0;212;1;0;2010,05,17,15,56,49;2010,05,17,15,55,46;0;"";0;""
然而,仅仅通过使用该字符串就可以准确地了解问题所在,因为我自己没有经历过异常

另一个我确实有问题(即使在Eclipse中)的例子如下:

Msg Id;Sender Name;Sender Address;Sender AddressType;Prefix;Subject;Body;BodyType;Folder;Account;Msg Class;Content Length;Msg Size;Msg Flags;Msg Status;Modify Time;Delivery Time;Recipient Nbr;Recipients;Attachment Nbr;Attachments
0x00,0x00;"491703000000";"491703000000";;"";"Wir wünschen dem rainer alles gute und viel gesundheit! Bis nächste woche, wir hören uns bis dahin noch mal.. Liebe grüße aus md!";"";0;"\\%MDF3";"SMS";"IPM.SMStext";;;33;262144;2007,09,23,19,44,32;2007,09,23,19,44,31;1;"851980\;Gela\;+491739000000\;1\;0\;SMS";0;""
Msg Id;Sender Name;Sender Address;Sender AddressType;Prefix;Subject;Body;BodyType;Folder;Account;Msg Class;Content Length;Msg Size;Msg Flags;Msg Status;Modify Time;Delivery Time;Recipient Nbr;Recipients;Attachment Nbr;Attachments
0x00,0x00;"Jonas/M";"\"Jonas/M\" <+46737000000>";;"";"Den går 28 ";"";2;"\\%MDF4";"SMS";"IPM.SMStext";0;24;0;0;2011,03,12,21,15,19;2011,03,12,21,16,17;0;"";0;""
0x00,0x00;"Don Vär";"\"Don Vär\" <+46709000000>";;"";"försöke® dhdjhdhhdjehdejehţýùhbfvfghjujhuikjkłánjajnxsjajmsxnsmajmkjsnshdjnsjmwkjhdnjsjmwkjdhjjdewjjwjwjw®";"";2;"\\%MDF1";"SMS";"IPM.SMStext";0;212;1;0;2010,05,17,15,56,49;2010,05,17,15,55,46;0;"";0;""
致:


您可以先给我们一个PIM备份文件的示例,您可以读取,而德国用户无法读取

事实上,您偶尔会得到一个UnicodeEncodeError(注意编码而不是解码),这是非常重要的。是否要更改代码以显示您得到的确切错误消息和回溯,而不是抑制它们

您是否在Linux/OSX/Windows上运行此功能?如果是windows,在命令提示窗口中?如果是,CHCP命令告诉您什么?它告诉你的德国记者什么

你读过csv文档中关于Unicode的内容吗?情况就是这样:

>>> import csv
>>> r = csv.reader([u"\xA0"])
>>> r.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 0: ordinal not in range(128)
>>>
导入csv >>>r=csv.reader([u”\xA0”]) >>>r.下一步() 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 UnicodeEncodeError:“ascii”编解码器无法对位置0中的字符u'\xa0'进行编码:序号不在范围内(128) >>> 如果您采取以下步骤,您将有更好的机会实现此功能:

  • 读取文件中的原始字节
  • 使用UTF-16将字节字符串解码为Unicode
  • 用UTF-8编码Unicode字符串
  • 将UTF-8字符串拆分为行列表(使用
    str.splitlines()
  • 从列表中创建一个csv阅读器
  • 迭代行,将每个单元格从UTF-8解码为Unicode
  • 更新在您对问题的编辑中,我看不到任何东西可以让我改变以前的建议。您可以选择省略上面的步骤6(这会起作用,但很糟糕),或者包括步骤6并重写输出阶段,以使用
    [c]ElementTree
    lxml
    进行UTF-8编码、转义等。顺便说一句,您正在编写XML文件,说明它们是用UTF-8编码的。我无法重现这一点,因为我没有Eclipse,但我怀疑您在Eclipse下运行时编写的“OK”XML文件实际上是在
    cp1252
    中编码的。您用XML验证器试过了吗


    您的U+E403字符问题只是问题的一部分,您的脚本将只“工作”于csv模块在遇到
    unicode
    输入时选择的任何编码中表示的字符。该字符位于一个PUA(私人用户区)块中,该块用于供应商特定的内容(例如苹果符号)或应用程序内容。Python提供的任何编码都不包含它,因此无法正确呈现(因为它不是以已发布的字体呈现)。谷歌搜索(“表情E403”)并根据结果显示它可能是U+1F614长脸,Unicode 6.0中的新版本。

    如果输入是UCS-2,则解码为UCS-2,而不是UTF-16。据我所知(通过我的谷歌搜索),UCS-2和UTF-16在Python中几乎相同,在某种程度上,Python没有内置的UCS-2编解码器,而是更喜欢UTF-16。此外,我没有得到任何例外这一事实意味着它适用于所有(或至少大多数)意图和目的。使用
    decode('utf-16-le')
    也没有帮助。哦,好吧,也许这是我的一个愚蠢的想法。在任何情况下,尝试使用
    编解码器。打开
    并将其传递给
    csv.reader
    ,而不是手动解码/拆分。如果同一输入有不同的行为,这几乎可以肯定是由于您的区域设置与您的用户不同造成的。@Pie21:您解决了问题吗?我一直支持您,直到您决定将抽象Unicode编码为UTF-8,但仍在使用它。您只希望在程序中使用常规解码的Unicode字符串,而不是编码的字节字符串。隐式解码计算机上的所有内容
    >>> import csv
    >>> r = csv.reader([u"\xA0"])
    >>> r.next()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 0: ordinal not in range(128)
    >>>