如何以原始语言打印unicode字符串的元组(不是u'foo'形式)

时间:2009-03-07 04:44:53

标签: python unicode

我有一个unicode对象元组列表:

>>> t = [('亀',), ('犬',)]

打印出来,我得到:

>>> print t
[('\xe4\xba\x80',), ('\xe7\x8a\xac',)]

我猜是这些字符串的utf-8字节码表示列表?

但我希望看到的是惊喜:

[('亀',), ('犬',)]

但是我在将字节码恢复为人类可读形式方面遇到了过多的麻烦。

6 个答案:

答案 0 :(得分:7)

  

但我希望看到的是惊喜:

     

[('亀',),('犬',)]

你想看到它打印出来的是什么?因为如果它是控制台,它根本不能保证您的控制台可以显示这些字符。这就是为什么Python的'repr()'对象表示用于\ -escapes的安全选项,你总能在屏幕上看到它并轻松输入。

作为先决条件,您应该使用Unicode字符串(u'')。而且,正如Matthew所提到的,如果你想能够直接在源代码中编写u'亀',你需要确保Python可以读取文件的编码。对于偶尔使用非ASCII字符,最好坚持使用转义版本u'\ u4e80',但是当你想要阅读很多东亚文本时,“#coding = utf-8”是绝对是要走的路。

  

print'[%s]'%','。join([','。join('(%s,)'%','。join(ti)for ti in t)])

这将打印用引号打开的字符。你真的想要:

def reprunicode(u):
    return repr(u).decode('raw_unicode_escape')

print u'[%s]' % u', '.join([u'(%s,)' % reprunicode(ti[0]) for ti in t])

这样可行,但是如果控制台不支持Unicode(这在Windows上特别麻烦),你会得到一个很大的旧UnicodeError。

在任何情况下,这都很重要,因为您在这里看到的对象的repr()通常不会进入应用程序的公共用户界面;它只适用于编码员。

但是,您会很高兴知道Python 3.0的行为完全符合您的要求:

  • plain''没有'u'前缀的字符串现在是Unicode字符串
  • repr()逐字显示大多数Unicode字符
  • 更好地支持Windows控制台中的Unicode(如果你的环境不是UTF-8,你仍然可以在Unix上获得UnicodeError)

Python 3.0有点新,而且库不太受支持,但它可能更适合您的需求。

答案 1 :(得分:3)

首先,你的帖子中存在轻微的误解。如果您定义这样的列表:

>>> t = [('亀',), ('犬',)]

...那些不是您定义的unicode,而是str s。如果您想拥有unicode类型,则必须在字符前添加u

>>> t = [(u'亀',), (u'犬',)]

但我们假设你真的想要str,而不是unicode。主要问题是,列表(或元组)的__str__方法实际上等于其__repr__方法(返回一个字符串,在评估时,它将创建完全相同的对象)。由于__repr__方法应该与编码无关,因此字符串可以以最安全的模式表示,即ASCII范围之外的每个字符都表示为十六进制字符(例如\xe4)。

不幸的是,据我所知,没有用于打印区域设置感知的列表的库方法。您可以使用几乎通用的函数,如下所示:

def collection_str(collection):
    if isinstance(collection, list):
        brackets = '[%s]'
        single_add = ''
    elif isinstance(collection, tuple):
        brackets = '(%s)'
        single_add =','
    else:
        return str(collection)
    items = ', '.join([collection_str(x) for x in collection])
    if len(collection) == 1:
        items += single_add
    return brackets % items

>>> print collection_str(t)
[('亀',), ('犬',)]

请注意,这不适用于所有可能的集合(例如集合和字典),但很容易扩展它以处理这些集合。

答案 2 :(得分:2)

Python源代码文件严格为ASCII,因此除非指定编码,否则必须使用\u转义序列。请参阅PEP 0263

#!/usr/bin/python
# coding=utf-8
t = [u'亀', u'犬']
print t

当您将数组传递给print时,Python会使用Python的rules for string conversions将对象转换为字符串。此类转换的输出是为eval()设计的,这就是您看到\u序列的原因。基于bobince的解决方案,这是一个解决问题的方法。控制台必须接受Unicode,否则会引发异常。

t = [(u'亀',), (u'犬',)]
print repr(t).decode('raw_unicode_escape')

答案 3 :(得分:0)

尝试:

import codecs, sys
sys.stdout = codecs.getwriter('utf8')(sys.stdout)

答案 4 :(得分:0)

所以这看起来像我想要的那样:

print '[%s]' % ', '.join([', '.join('(%s,)' % ', '.join(ti) for ti in t)])


>>> t = [('亀',), ('犬',)]
>>> print t
[('\xe4\xba\x80',), ('\xe7\x8a\xac',)]
>>> print '[%s]' % ', '.join([', '.join('(%s,)' % ', '.join(ti) for ti in t)])
[(亀,), (犬,)]

当然有更好的方法。

(但到目前为止的其他两个答案并没有导致原始字符串按照需要打印出来。)

答案 5 :(得分:0)

似乎人们错过了人们想要的东西。当我从元组打印unicode时,我只想摆脱'u''[''('和引号。我们想要的是下面的函数。 在搜索网络之后,它似乎是获取原子可显示数据的最简洁方法。 如果数据不在元组或列表中,我认为这个问题不存在。

def Plain(self, U_String) :
          P_String = str(U_String)
          m=re.search("^\(\u?\'(.*)\'\,\)$", P_String)
          if (m) :  #Typical unicode
             P_String = m.group(1).decode("utf8")
          return P_String