20

当我open()用来打开文件时,我无法编写 unicode 字符串。我了解到我需要使用codecs和打开带有 Unicode 编码的文件(请参阅http://docs.python.org/howto/unicode.html#reading-and-writing-unicode-data)。

现在我需要创建一些临时文件。我尝试使用该tempfile库,但它没有任何编码选项。当我尝试在临时文件中写入任何 unicode 字符串时tempfile,它会失败:

#!/usr/bin/python2.6
# -*- coding: utf-8 -*-
import tempfile
with tempfile.TemporaryFile() as fh:
  fh.write(u"Hello World: ä")
  fh.seek(0)
  for line in fh:
    print line

如何在 Python 中使用 Unicode 编码创建临时文件?

编辑:

  1. 我正在使用 Linux,我收到的此代码的错误消息是:

    Traceback (most recent call last):
      File "tmp_file.py", line 5, in <module>
        fh.write(u"Hello World: ä")
    UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 13: ordinal not in range(128)
    
  2. 这只是一个例子。在实践中,我正在尝试编写一些 API 返回的字符串。
4

7 回答 7

20

其他人的答案都是正确的,我只想澄清发生了什么:

'foo'字面量和字面量的区别在于u'foo'前者是字节串,后者是Unicode对象。

首先,了解Unicode是字符集。UTF-8 是编码。Unicode 对象与前者有关——它是一个 Unicode 字符串,不一定是 UTF-8 字符串。在您的情况下,字符串文字的编码将是 UTF-8,因为您在文件的第一行中指定了它。

要从字节字符串中获取 Unicode 字符串,请调用以下.encode()方法:

>>>> u"ひらがな".encode("utf-8") == "ひらがな"
True

同样,您可以在调用中调用您的 string.encodewrite并达到与仅删除u.

如果您没有在顶部指定编码,假设您正在从另一个文件读取 Unicode 数据,那么您将指定它在到达 Python 字符串之前的编码。这将决定它如何以字节表示(即str类型)。

那么,您得到的错误仅仅是因为tempfile模块需要一个str对象。这并不意味着它不能处理 unicode,只是它希望您传入一个字节字符串而不是 Unicode 对象——因为如果不指定编码,它就不会知道如何将其写入临时文件。

于 2012-05-08T00:59:29.517 回答
15

tempfile.TemporaryFile在 Python 3 中具有编码选项

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import tempfile
with tempfile.TemporaryFile(mode='w+', encoding='utf-8') as fh:
  fh.write("Hello World: ä")
  fh.seek(0)
  for line in fh:
    print(line)

请注意,现在您需要指定 mode='w+' 而不是默认的二进制模式。另请注意,字符串文字在 Python 3 中是隐式的 Unicode,没有u修饰符。

如果你坚持使用Python 2.6,临时文件总是二进制的,你需要在将 Unicode 字符串写入文件之前对其进行编码:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import tempfile
with tempfile.TemporaryFile() as fh:
  fh.write(u"Hello World: ä".encode('utf-8'))
  fh.seek(0)
  for line in fh:
    print line.decode('utf-8')

Unicode 指定字符集,而不是编码,因此无论哪种情况,您都需要一种方法来指定如何对 Unicode 字符进行编码!

于 2013-05-07T13:31:06.007 回答
7

由于我正在使用应该在 Python 2 和 Python 3 中运行的 TemporaryFile 对象的 Python 程序,因此我发现手动编码所有编写为 UTF-8 的字符串并不令人满意,就像其他答案所暗示的那样。

相反,我编写了以下小的 polyfill(因为我在六个中找不到类似的东西)来将二进制文件类对象包装成一个 UTF-8 文件类对象:

from __future__ import unicode_literals
import sys
import codecs
if sys.hexversion < 0x03000000:
    def uwriter(fp):
        return codecs.getwriter('utf-8')(fp)
else:
    def uwriter(fp):
        return fp

它以下列方式使用:

# encoding: utf-8
from tempfile import NamedTemporaryFile
with uwriter(NamedTemporaryFile(suffix='.txt', mode='w')) as fp:
    fp.write('Hællo wörld!\n')
于 2015-03-20T10:31:24.487 回答
5

我想出了一个解决方案:创建一个不会自动删除的临时文件tempfile,关闭它并使用以下命令再次打开它codecs

#!/usr/bin/python2.6
# -*- coding: utf-8 -*-

import codecs
import os
import tempfile

f = tempfile.NamedTemporaryFile(delete=False)
filename = f.name
f.close()

with codecs.open(filename, 'w+b', encoding='utf-8') as fh:
  fh.write(u"Hello World: ä")
  fh.seek(0)
  for line in fh:
    print line

os.unlink(filename)
于 2012-05-08T00:14:19.447 回答
1

您正在尝试将 unicode 对象写入(u"...")应使用编码字符串的临时文件("...")。您不必显式传递"encode="参数,因为您已经在第二行中说明了编码("# -*- coding: utf-8 -*-")。只需使用fh.write("ä")而不是,fh.write(u"ä")你应该没问题。

于 2012-05-08T00:33:38.350 回答
-1

删除 u 使您的代码对我有用:

fh.write("Hello World: ä")

我想这是因为它已经是 unicode 了。

于 2012-05-08T00:24:54.920 回答
-1

将 sys 设置为默认编码为 UTF-8 将解决编码问题

import sys
reload(sys)
sys.setdefaultencoding('utf-8') #set to utf-8 by default this will solve the errors

import tempfile
with tempfile.TemporaryFile() as fh:
  fh.write(u"Hello World: ä")
  fh.seek(0)
  for line in fh:
    print line
于 2018-02-12T09:15:32.010 回答