gpt4 book ai didi

Python 不能正确解释 UTF8

转载 作者:行者123 更新时间:2023-12-01 05:44:11 25 4
gpt4 key购买 nike

我知道类似的问题已经被问过一百万次了,但是尽管阅读了很多问题,我还是找不到适合我情况的解决方案。
我有一个 django 应用程序,我在其中创建了一个管理脚本。该脚本读取一些文本文件,并将它们输出到终端(稍后它将对内容做更多有用的事情,但我仍在对其进行测试)并且字符带有转义序列,如 \xc3\xa5而不是预期的å .由于该转义序列意味着 Ã¥ ,这是对 å 的常见误解。由于编码问题,我怀疑至少有两个地方出了问题。但是,我不知道在哪里 - 我已经检查了我能想到的所有可能的罪魁祸首:

  • 终端编码为UTF-8; echo $LANGen_US.UTF-8
  • 文本文件以 UTF-8 编码; file *在它们所在的目录中,所有条目都被列为“UTF-8 Unicode 文本”,除了一个不包含任何非 ASCII 字符并被列为“ASCII 文本”的条目。运行iconv -f ascii -t utf8 thefile.txt > utf8.txt在该文件上生成另一个具有 ASCII 文本编码的文件。
  • Python 脚本都是 UTF-8(或者,在某些情况下,是没有非 ASCII 字符的 ASCII)。我尝试在我的管理脚本中插入带有一些特殊字符的注释,以强制它保存为 UTF-8,但它并没有改变行为。以上对文本文件的观察也适用于所有 Python 脚本文件。
  • 处理文本文件的 Python 脚本有 # -*- encoding: utf-8 -*-在顶部;前面唯一的一行是 #!/usr/bin/python3 ,但我都尝试过更改为 .../python对于 Python 2.7 或将其完全删除以将其留给 Django,但没有结果。
  • 根据the documentation , “Django 原生支持 Unicode 数据”,所以我可以在应用程序的任何地方“安全地传递 Unicode 字符串”。

  • 我真的想不出其他地方可以在链中寻找非 UTF-8 链接。我在哪里可能错过了更改为 UTF-8 的设置?
    为了完整起见:我正在读取带有 lines = file.readlines() 的文件并使用标准 print() 打印功能。两端都不会发生手动编码或解码。
    更新:
    针对评论中的提问:
  • print(sys.getdefaultencoding(), sys.stdout.encoding, f.encoding)产量 ('ascii', 'UTF-8', None)对于所有文件。
  • 我开始编译一个 SSCCE,很快发现问题只有在我尝试打印元组中的值时才会出现。换句话说,print(lines[0].strip())工作正常,但 print(lines[0].strip(), lines[1].strip())才不是。添加 .decode('utf-8')产生一个元组,其中两个字符串都标有前置 u\xe5 ( å 的正确转义序列)而不是之前的奇数字符 - 但我不知道如何将它们打印为常规字符串,没有转义字符。我测试了另一个对 .decode('utf-8') 的调用以及包装str()但都失败了UnicodeEncodeError提示\xe5不能用 ascii 编码。由于单个字符串可以正常工作,我不知道还要测试什么。

  • SSCCE:
    # -*- coding: utf-8 -*-

    import os, sys

    for root,dirs,files in os.walk('txt-songs'):
    for filename in files:
    with open(os.path.join(root,filename)) as f:
    print(sys.getdefaultencoding(), sys.stdout.encoding, f.encoding)

    lines = f.readlines()
    print(lines[0].strip()) # works
    print(lines[0].strip(), lines[1].strip()) # does not work

    最佳答案

    这里最大的问题是您将 Python 2 和 Python 3 混合在一起。特别是,您编写了 Python 3 代码,并且尝试在 Python 2.7 中运行它。但在此过程中还有一些其他问题。所以,让我试着解释所有的问题。

    I started compiling an SSCCE, and quickly found that the problem is only there if I try to print the value in a tuple. In other words, print(lines[0].strip()) works fine, but print(lines[0].strip(), lines[1].strip()) does not.



    这里的第一个问题是 str元组(或任何其他集合)包括 repr ,而不是 str ,它的元素。解决此问题的简单方法是不打印集合。在这种情况下,根本没有理由打印一个元组。您拥有它的唯一原因是您已经为打印而构建了它。只需执行以下操作:
    print '({}, {})'.format(lines[0].strip(), lines[1].strip())

    如果你已经在一个变量中有一个集合,并且你想打印出每个元素的 str,你必须明确地这样做。您可以使用以下命令打印每个 str 的 repr:
    print tuple(map(str, my_tuple))

    ...或直接打印每个 str :
    print '({})'.format(', '.join(map(str, my_tuple)))

    请注意,我使用的是上面的 Python 2 语法。那是因为如果你真的使用 Python 3,一开始就没有元组,也不需要调用 str .

    你有一个 Unicode 字符串。在 Python 3 中, unicodestr是同一类型。但在 Python 2 中,它是 bytesstr是相同的类型,和 unicode是不同的。因此,在 2.x 中,您没有 str然而,这就是为什么您需要调用 str .

    Python 2 也是 print(lines[0].strip(), lines[1].strip()) 的原因打印一个元组。在 Python 3 中,这是对 print 的调用。以两个字符串作为参数的函数,因此它将打印出由空格分隔的两个字符串。在 Python 2 中,它是 print带有一个参数的语句,它是一个元组。

    如果你想编写在 2.x 和 3.x 中工作相同的代码,你要么需要避免打印多个参数,要么使用像 six.print_ 这样的包装器。 ,或执行 from __future__ import print_function ,或者要非常小心地做一些丑陋的事情,比如添加额外的括号,以确保你的元组在两个版本中都是元组。

    所以,在 3.x 中,你有 str对象,您只需将它们打印出来。在 2.x 中,您有 unicode对象,而您正在打印出它们的 repr .您可以更改它以打印出他们的 str ,或者首先避免打印元组……但这仍然无济于事。

    为什么?好吧,在任何一个版本中打印任何内容,只需调用 str然后将其传递给 sys.stdio.write .但在 3.x 中, str表示 unicode , 和 sys.stdioTextIOWrapper ;在 2.x 中, str表示 bytes , 和 sys.stdio是二进制 file .

    因此,最终发生的伪代码是:
    sys.stdio.wrapped_binary_file.write(s.encode(sys.stdio.encoding, sys.stdio.errors))

    sys.stdio.write(s.encode(sys.getdefaultencoding()))

    而且,正如您所看到的,它们会做不同的事情,因为:

    print(sys.getdefaultencoding(), sys.stdout.encoding, f.encoding) yields ('ascii', 'UTF-8', None)



    您可以在此处使用 io.TextIOWrapper 模拟 Python 3或 codecs.StreamWriter然后使用 print >>f, …f.write(…)而不是 print ,或者您可以显式编码您的所有 unicode像这样的对象:
    print '({})'.format(', '.join(element.encode('utf-8') for element in my_tuple)))

    但实际上,处理所有这些问题的最佳方法是在 Python 3 解释器而不是 Python 2 解释器中运行现有的 Python 3 代码。

    如果您想要或需要使用 Python 2.7,那很好,但您必须编写 Python 2 代码。如果您想编写 Python 3 代码,那很好,但您必须运行 Python 3.3。如果你真的想编写在两者中都能正常工作的代码,你可以,但这是额外的工作,并且需要更多的知识。

    更多详情,请参阅 What's New In Python 3.0 (“打印是一个函数”和“文本与数据而不是 Unicode 与 8 位”部分),尽管这是从解释 3.x 到 2.x 用户的角度编写的,这与你需要。 3.x2.x Unicode HOWTO 的版本也可能有所帮助。

    关于Python 不能正确解释 UTF8,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16681712/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com