【问题标题】:Write to UTF-8 file in Python在 Python 中写入 UTF-8 文件
【发布时间】:2010-10-30 08:50:24
【问题描述】:

我真的对codecs.open function 感到困惑。当我这样做时:

file = codecs.open("temp", "w", "utf-8")
file.write(codecs.BOM_UTF8)
file.close()

它给了我错误

UnicodeDecodeError: 'ascii' 编解码器无法在位置解码字节 0xef 0:序数不在范围内(128)

如果我这样做:

file = open("temp", "w")
file.write(codecs.BOM_UTF8)
file.close()

效果很好。

问题是为什么第一种方法会失败?以及如何插入 bom?

如果第二种方法是正确的做法,那么使用codecs.open(filename, "w", "utf-8")的意义何在?

【问题讨论】:

  • 不要在 UTF-8 中使用 BOM。 请。
  • @tchrist 嗯?为什么不呢?
  • @SalmanPK BOM 在 UTF-8 中不需要,只会增加复杂性(例如,您不能仅连接 BOM 文件并使用有效文本生成结果)。见this Q&A;不要错过Q下的大评论

标签: python utf-8 character-encoding byte-order-mark


【解决方案1】:

如果您使用的是 pandas.to_excel() 等 Pandas I/O 方法,请添加编码参数,例如

pd.to_excel("somefile.xlsx", sheet_name="export", encoding='utf-8')

这适用于我认为的大多数国际角色。

【讨论】:

    【解决方案2】:

    使用这个非常简单。 不需要任何库。

    with open('text.txt', 'w', encoding='utf-8') as f:
        f.write(text)
    

    【讨论】:

      【解决方案3】:

      我认为问题在于codecs.BOM_UTF8 是字节字符串,而不是 Unicode 字符串。我怀疑文件处理程序试图根据“我打算将 Unicode 编写为 UTF-8 编码文本,但你给了我一个字节字符串!”来猜测你的真正意思。

      尝试直接为字节顺序标记编写 Unicode 字符串(即 Unicode U+FEFF),以便文件将其编码为 UTF-8:

      import codecs
      
      file = codecs.open("lol", "w", "utf-8")
      file.write(u'\ufeff')
      file.close()
      

      (这似乎给出了正确的答案 - 一个字节为 EF BB BF 的文件。)

      编辑:S. Lott 的 suggestion 使用“utf-8-sig”作为编码比自己明确编写 BOM 更好,但我将把这个答案留在这里,因为它解释了之前出了什么问题.

      【讨论】:

      • 警告:open和open是不一样的。如果您执行“从编解码器导入打开”,它将与您只需键入“打开”不同。
      • 你也可以使用 codecs.open('test.txt', 'w', 'utf-8-sig') 代替
      • 我收到“TypeError: an integer is required (got type str)”。我不明白我们在这里做什么。有人可以帮忙吗?我需要将字符串(段落)附加到文本文件中。在写入之前我需要先将其转换为整数吗?
      • @Mugen:就我所见,我编写的 exact 代码运行良好。我建议你问一个新问题,显示确切你有什么代码,以及错误发生在哪里。
      • @Mugen 你需要打电话给codecs.open 而不仅仅是open
      【解决方案4】:

      阅读以下内容:http://docs.python.org/library/codecs.html#module-encodings.utf_8_sig

      这样做

      with codecs.open("test_output", "w", "utf-8-sig") as temp:
          temp.write("hi mom\n")
          temp.write(u"This has ♭")
      

      生成的文件是带有预期 BOM 的 UTF-8。

      【讨论】:

      • 谢谢。那行得通(Windows 7 x64,Python 2.7.5 x64)。当您以“a”(附加)模式打开文件时,此解决方案效果很好。
      • 这对我不起作用,Windows 上的 Python 3。我不得不使用 open(file_name, 'wb') as bomfile: bomfile.write(codecs.BOM_UTF8) 然后重新打开文件以进行追加。
      • 可以添加temp.close() ?
      • @user2905353:不需要;这是由opencontext management 处理的。
      【解决方案5】:

      我使用 file *nix 命令将未知字符集文件转换为 utf-8 文件

      # -*- encoding: utf-8 -*-
      
      # converting a unknown formatting file in utf-8
      
      import codecs
      import commands
      
      file_location = "jumper.sub"
      file_encoding = commands.getoutput('file -b --mime-encoding %s' % file_location)
      
      file_stream = codecs.open(file_location, 'r', file_encoding)
      file_output = codecs.open(file_location+"b", 'w', 'utf-8')
      
      for l in file_stream:
          file_output.write(l)
      
      file_stream.close()
      file_output.close()
      

      【讨论】:

      • 使用# coding: utf8而不是# -*- coding: utf-8 -*-,这样更容易记住。
      • 我真的很想在 Windows 上看到类似的东西
      【解决方案6】:

      @S-Lott 给出了正确的过程,但扩展 Unicode 问题,Python 解释器可以提供更多见解。

      Jon Skeet 关于codecs 模块是正确的(不寻常的) - 它包含字节字符串:

      >>> import codecs
      >>> codecs.BOM
      '\xff\xfe'
      >>> codecs.BOM_UTF8
      '\xef\xbb\xbf'
      >>> 
      

      再选一个,BOM有一个标准的Unicode名字,可以这样输入:

      >>> bom= u"\N{ZERO WIDTH NO-BREAK SPACE}"
      >>> bom
      u'\ufeff'
      

      也可以通过unicodedata访问:

      >>> import unicodedata
      >>> unicodedata.lookup('ZERO WIDTH NO-BREAK SPACE')
      u'\ufeff'
      >>> 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-06
        • 1970-01-01
        • 2020-08-09
        • 2018-07-18
        • 2010-10-04
        • 2015-02-13
        • 2011-06-16
        相关资源
        最近更新 更多