在Python中打印转义的Unicode

5
>>> s = 'auszuschließen'
>>> print(s.encode('ascii', errors='xmlcharrefreplace'))
b'auszuschließen'
>>> print(str(s.encode('ascii', errors='xmlcharrefreplace'), 'ascii'))
auszuschließen

有没有更好的方法在不使用b''的情况下打印任何字符串?

编辑:

我只是想从Python中打印转义字符,唯一的问题是当我这么做时,Python会添加"b''"。

如果我想在像Windows 7这样的简陋终端中看到实际字符,则会得到以下结果:

Traceback (most recent call last):
  File "Mailgen.py", line 378, in <module>
    marked_copy = mark_markup(language_column, item_row)
  File "Mailgen.py", line 210, in mark_markup
    print("TP: %r" % "".join(to_print))
  File "c:\python32\lib\encodings\cp437.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_map)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u2026' in position 29: character maps to <undefined>

1
你为什么不直接使用print(s)呢?为什么需要编码为ASCII? - jcollado
因为我不认为我的终端支持我代码处理的每个奇怪字符。 - Cees Timmerman
1
print(str(s.encode('ascii', errors='ignore'), 'ascii'))会更漂亮,无论如何。 - Lennart Regebro
1
我已经更新了我的回答。虽然它可以回答你的问题,但似乎解决了错误的问题。在我看来,更重要的问题是:为什么你想要一个“漂亮”的输出,而本质上这只是调试信息(字符串中的Unicode字符)?这是日志记录、实际程序用户界面还是应该传输给另一个程序的标准输出,还是其他什么? - Lennart Regebro
2
你也可以设置环境变量PYTHONIOENCODING=cp437:backslashreplace,然后使用print(s)。我在答案中没有提到它,因为如果设置不正确,Python可能会崩溃 - jfs
显示剩余4条评论
4个回答

4

为了进行调试,可以查看ASCII表示(类似于Python 2中的repr()):

print(ascii('auszuschließen…'))
# -> 'auszuschlie\xdfen\u2026'

打印字节:

sys.stdout.buffer.write('auszuschließen…'.encode('ascii', 'xmlcharrefreplace'))
# -> auszuschlie&#223;en&#8230;

经过仔细检查,我在终端中运行sys.stdout.buffer.write('auszuschließen…test'.encode('ascii', 'xmlcharrefreplace'))后输出:auszuschließen.test24。我不喜欢特殊情况(未捕获的返回值会被打印出来),所以我会采用decode()解决方案。 - Cees Timmerman
1
@Cees Timmerman:不是这样的。您可能把它与交互式解释器(例如ipython,bpython,idle或仅带参数的python)混淆了。在这种情况下,您不需要打印字符串;解释器会自己回显其值。 - jfs
1
@J.F.Sebastian:是的。关键是他想要打印而不带有b''。只使用ascii打印会去掉b,但保留''。 - Lennart Regebro
@J.F.Sebastian:我的意思是 >>> sys.stdout.buffer.write('auszuschließen.test'.encode('ascii', 'xmlcharrefreplace')) auszuschließen.test24 - Cees Timmerman

3
>>> s='auszuschließen…'
>>> s
'auszuschließen…'
>>> print(s)
auszuschließen…
>>> b=s.encode('ascii','xmlcharrefreplace')
>>> b
b'auszuschlie&#223;en&#8230;'
>>> print(b)
b'auszuschlie&#223;en&#8230;'
>>> b.decode()
'auszuschlie&#223;en&#8230;'
>>> print(b.decode())
auszuschlie&#223;en&#8230;

你从一个Unicode字符串开始。将其编码为ascii会创建一个包含所需字符的bytes对象。Python不会打印它,除非将其转换回字符串,并且默认转换会加入b和引号。使用decode显式地将其转换回字符串;默认编码为utf-8,由于你的bytes仅由ascii组成,而asciiutf-8的子集,因此可以保证它能正常工作。

这是目前最优雅的解决方案。请注意,我的终端会将“…”静默地转换为“。”。 - Cees Timmerman

1

并非所有终端都能处理超过某种8位字符集,这是事实。但无论你做什么,它们都不会处理。

打印Unicode字符串将(假定您的操作系统正确设置了终端)会产生最佳结果,这意味着终端无法打印的字符将被替换为一些字符,例如问号或类似字符。自己进行翻译不会真正改进情况。

更新:

由于您想知道字符串中有哪些字符,因此实际上要知道它们的Unicode代码,或在这种情况下的XML等效代码。那比打印更多的是检查,通常b''部分本身并不是问题。

但是您可以轻松而粗略地摆脱它,就像这样:

print(repr(s.encode('ascii', errors='xmlcharrefreplace'))[2:-1])

追踪(Traceback)最近的调用(most recent call): 文件 "Mailgen.py",第378行,在<module>中: marked_copy = mark_markup(language_column, item_row) 文件 "Mailgen.py",第210行,在mark_markup中: print("TP: %r" % "".join(to_print)) 文件 "c:\python32\lib\encodings\cp437.py",第19行,在encode中: return codecs.charmap_encode(input,self.errors,encoding_map)[0] UnicodeEncodeError: 'charmap'编解码器无法在位置29处编码字符'\u2026':该字符映射到<undefined>。 - Cees Timmerman
@CeesTimmerman:看吧,这就是一个真正问题的开端。你应该提出一个问题。还要包括关于你的终端的信息。 - Lennart Regebro
如何在64位Windows 7企业版命令终端(以及其他终端)中Pythonically打印未知的Unicode字符串? - Cees Timmerman
@CeesTimmerman 您应该在原始问题中更新您在第一条评论中指定的细节(或者如果与此完全不同,则提出一个问题);这将改善问题并为更多人提供帮助的机会。 - casperOne
@casperOne 我只是想从Python中打印转义字符,我唯一的抱怨是当我这样做时,Python会添加“b''”。这个非答案重复了jcollado的问题。我应该在我的问题中重复我的回答吗? - Cees Timmerman
1
@CeesTimmerman 请停止在评论中提出额外的问题。如果这些细节不会改变问题的本质,请更新您的主要问题。 (http://meta.stackexchange.com/questions/106249/update-a-question-or-post-a-new-question) - casperOne

0

由于您使用的是 Python 3,因此您可以将 print(s) 写入控制台。

我同意,根据控制台的不同,它可能无法正确打印,但我想象自 2006 年以来大多数现代操作系统都可以处理 Unicode 字符串而不会出现太多问题。我鼓励您尝试一下并查看是否可行。

或者,您可以通过在 文件 中的任何行之前放置以下内容来强制执行编码(类似于 shebang):

# -*- coding: utf-8 -*-

这将强制解释器将其呈现为UTF-8。


这个64位的Windows 7企业版命令终端不喜欢打印不在CP437字符集中的字符,例如'\u2026'。 - Cees Timmerman
1
  1. # -*- coding: utf-8 -*- 是Python3的默认设置。
  2. 它不会改变 print(s) 的工作方式,只会影响如何解释字面字符串。
- jfs

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