如何在Python中将符号如●打印到文件中

8

我想在Python的文本文件中写入符号。我认为这与编码(utf-8)有关。以下是代码:

# -*- coding: utf-8 -*-
outFile = open('./myFile.txt', 'wb')
outFile.write("●")
outFile.close()

我得到的不是黑色的"●",而是"â—"。我该怎么解决?


2
谢谢你的回答!我发现问题是Wordpad不显示点,但记事本可以。所以实际上一开始就可以工作了。 - Jesper Lundin
Python 2 还是 Python 3?(提示:Py3 更好) - jeromej
然而,上述代码仍存在问题:它只能在以下情况下正常工作:(1)您的程序编辑器确实使用UTF-8(这可能不是事实),以及(2)使用与您的编程编辑器相同编码的文本文件查看器。您可以查看我的解决方案,该方案几乎可以在任何机器上为几乎任何用户提供“●”,无论他们选择的编码是什么。 - Eric O. Lebigot
@JeromeJ:这是Python 2。 - Jesper Lundin
@EOL 很好!知道了! - Jesper Lundin
6个回答

3

使用io包打开文件,才能使代码在python2python3都能运行,并将编码设置为utf8。在打印时,以Unicode字符串的形式输出。在写入时,也要写成Unicode字符串。

import io
outFile = io.open('./myFile.txt', 'w', encoding='utf8')
outFile.write(u'●')
outFile.close()

已测试通过Python 2.7.8Python 3.4.2


1
这仅适用于 Python 3,并且仅在所需的输出为 UTF-8 时才起作用(它不必与程序编辑器使用的编码相同,通常因机器而异,尤其是在 Windows 环境和某些国家/地区)。 - Eric O. Lebigot
@EOL,没错。我更新了我的答案,弥补了旧答案的不足之处。谢谢 :) - Alok Mysore
如果您必须在支持UTF-8的系统上使用它,那么您不需要添加太多内容到原始代码中,因为它会写入完全相同的文件! - Serge Ballesta

1
如果您使用的是Python 2,请使用codecs.open代替open,并使用unicode代替str:
# -*- coding: utf-8 -*-
import codecs
outFile = codecs.open('./myFile.txt', 'wb', 'utf-8')
outFile.write(u"●")
outFile.close()

在Python 3中,使用encoding关键字参数来传递给open函数:
# -*- coding: utf-8 -*-
outFile = open('./myFile.txt', 'w', encoding='utf-8')
outFile.write("●")
outFile.close()

0
>>> ec = u'\u25cf' # unicode("●", "UTF-8")
>>> open("/tmp/file.txt", "w").write(ec.encode('UTF-8'))

0
你的程序的作用是生成一个输出文件,编码方式和你的程序编辑器相同(除非你的程序编辑器使用它来保存文件,否则开头的 coding 不重要)。因此,如果你用一个使用和你的程序编辑器相同编码方式的程序打开 myFile.txt,一切看起来都很好。
这并不意味着你的程序适用于所有人。
为了达到这一点,你必须做两件事情。首先,你必须指定机器上用于文本文件的编码方式。这有点难以检测,但以下方法通常可以行得通:
# coding=utf-8  # Put your editor's encoding here

import codecs
import locale
import sys

# Selection of the first non-None, reasonable encoding:
out_encoding = (locale.getlocale()[1]
                or locale.getpreferredencoding()
                or sys.stdin.encoding or sys.stdout.encoding
                # Default:
                or "UTF8")

outFile = codecs.open('./myFile.txt', 'w', out_encoding)

请注意,在文件顶部指定正确的编码非常重要:这必须是您的程序编辑器的编码。
如果您知道输出文件所需的编码,可以直接将其放入open()中。否则,上面更通用和可移植的out_encoding表达式应适用于大多数用户在大多数计算机上(即,无论他们选择的编码是什么,他们都应该能够在结果文件中读取“●”——假设他们计算机的编码可以表示它)。
然后,您必须打印一个字符串,而不是字节:
outFile.write(u"●")

(请注意前导的u,表示“Unicode字符串”)。

为了更深入地理解问题,我的一个先前的答案应该非常有帮助:重定向到文件时出现UnicodeDecodeError


你的解决方案真的很好...不幸的是,在ISO-8859-1中没有表示弹头的字符!(或者我找不到它 :-() - Serge Ballesta
实际上,在Latin 1字符集中并不存在这个符号,也就是"•"。 - Eric O. Lebigot

0

这应该能解决问题

# -*- coding: utf-8 -*-
outFile = open('./myFile.txt', 'wb')
outFile.write(u"\u25CF".encode('utf-8'))
outFile.close()

看一下this


0

非常抱歉,但是在将符号写入文本文件时没有说明文件的编码方式是毫无意义的。

乍一看可能不明显,但是文本文件确实是编码的,并且可以用不同的方式进行编码。如果您只有字母(大写和小写,但没有重音符号),数字和简单符号(所有ASCII代码低于128的内容),那么一切都应该没问题,因为ASCII 7位现在是标准的,在主要编码中这些字符具有相同的表示。

但是,一旦您获得真正的符号或带重音符号的字符,它们的表示会因编码而异。例如,符号●在UTF-8表示中的Python编码为:\xe2\x97\x8f。更糟糕的是,它不能用Latin1(ISO-8859-1)编码表示。

另一个例子是法语的e accent aigué,在UTF8中表示为\xc3\xa9(注意2个字节),但在Latin1中表示为\x89(仅一个字节)。

所以我在我的Ubuntu系统上使用UTF8编码和命令cat myFile.txt来测试了你的代码...正确地显示了弹头符号!

sba@sba-ubuntu:~/stackoverflow$ cat myFile.txt 
●sba@sba-ubuntu:~/stackoverflow$ 

总之:

您的代码以UTF8编码正确地将项目符号写入文件。如果您的系统使用本地其他编码(ISO-8859-1或其变体Windows-1252),则无法原生转换它,因为这个字符在这些编码中根本不存在。

但是,您始终可以在支持不同编码的文本编辑器中查看它,例如存在于所有主要系统上的优秀vim


以上证明:

在Windows 7电脑上,我打开了一个vim窗口,并使用:set encoding='utf8'指令让它接受utf8编码。然后,我将原始代码从OP粘贴到了一个名为foo.py的文件中并保存。

我打开了一个cmd.exe窗口并执行了python foo.py(使用Python 2.7):它创建了一个名为myFile.txt的文件,其中包含3个字节(十六进制):e2 97 8f这是圆点符号的utf8表示形式(我可以通过vim工具/十六进制转换进行确认)。

我甚至可以在idle中打开myFile.txt并实际看到圆点符号。甚至notepad.exe也可以显示圆点符号!

因此,即使在不原生接受utf-8的Windows 7电脑上,来自OP的代码仍然可以正确生成一个文本文件,当使用接受UTF-8的文本编辑器打开时,其中包含圆点符号

当然,如果我尝试以Latin1模式用vim打开myFile.txt,在一个编码为850的cmd窗口上,type myFile.txt显示ÔùÅ,而使用1252代码页(Latin1的变体):â—。

总之,原始OP代码创建了一个正确的UTF-8编码文件 - 读取部分需要正确解释UTF-8。


我还修正了你所说的关于“Unicode表示”的内容,这实际上是不存在的:你实际上引用的是UTF-8表示(这不是Unicode中唯一的编码方式)。 - Eric O. Lebigot
最后,"正确地使用UTF8编码"的代码并不完全准确:只有在程序编辑器确实使用UTF8时才是如此(这在Windows上尤其不常见)。关于问题中的代码的一般事实是,它的输出文件与程序编辑器具有相同的编码(顶部的coding并不重要)。 - Eric O. Lebigot
它确实会写一个文件,可以用任何能处理UTF-8的编辑器来读取。从这个意义上说,它确实会写一个UTF-8编码的文本文件。而且vim(或gvim)在Windows中运行得非常完美(它是我最喜欢的通用文本编辑器)。无论如何,感谢修复 :-) - Serge Ballesta
我必须反驳:只需在不使用UTF-8的编辑器/机器中输入原始程序,运行程序,您将看到输出文件不是UTF-8。即使您没有轻松访问这样的编辑器,您也可以将顶部行更改为“# coding=latin1”(在忽略此行的纯文本编辑器中):您将看到输出不是Latin 1:换句话说,顶部行对于输出的编码无关紧要。原始程序中唯一的规范编码是程序编辑器使用的编码。因此,我认为该程序通常不会写入UTF-8。 - Eric O. Lebigot
@EOL:顶部的 # -*- coding: utf-8 -*- 指示 Python 解释器(以及可选的一些文本编辑器,如 idle)输入脚本文件是 utf8 编码的,并且对输出没有直接影响。但请参见我的编辑。 - Serge Ballesta
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接