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

时间:2012-05-08 00:08:07

标签: python unicode temporary-files

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

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

#!/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返回的字符串。

7 个答案:

答案 0 :(得分:19)

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

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

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

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

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

同样,您可以在write调用中调用string.encode,并获得与删除u相同的效果。

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

然后,您获得的错误仅仅是因为tempfile模块需要str个对象。这个 意味着它无法处理unicode,只是它希望你传入一个字节字符串而不是Unicode对象 - 因为没有你指定编码,它不知道如何将它写入临时文件。

答案 1 :(得分:9)

tempfile.TemporaryFile有encoding option in 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, temporary files,则始终是二进制文件,并且需要先对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字符!

答案 2 :(得分:6)

我找到了一个解决方案:创建一个未使用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)

答案 3 :(得分:6)

由于我正在开发一个Python程序,其中TemporaryFile对象应该在Python 2和Python 3中运行,因此我不觉得手动编码所有写为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')

答案 4 :(得分:1)

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

答案 5 :(得分:0)

放弃你让你的代码适合我:

fh.write("Hello World: ä")

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

答案 6 :(得分:0)

将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