如何将非ascii字符打印为\ uXXXX

时间:2016-03-25 14:45:56

标签: python python-3.x unicode python-3.4 non-ascii-characters

# what I currently have

print('你好')

# 你好
# this is what I want

print('你好')

# \uXXXX \uXXXX

我该怎么做?我想将字符串中的所有非ascii字符打印为unicode escape literals

3 个答案:

答案 0 :(得分:9)

您可以使用ascii() function将字符串转换为使用非ASCII,不可打印字符转换为转义序列的调试表示:

  

作为repr(),返回包含对象的可打印表示的字符串,但使用repr()\x转义\u返回的字符串中的非ASCII字符或\U逃脱。

对于U + 0100-U + FFFF范围内的Unicode代码点,它使用\uhhhh转义符;对于Latin-1范围(U + 007F-U + 00FF),使用\xhh转义。请注意,输出有资格作为有效的Python语法来重新创建字符串,因此包括引号:

>>> print('你好')
你好
>>> print(ascii('你好'))
'\u4f60\u597d'
>>> print(ascii('ASCII is not changed, Latin-1 (åéîøü) is, as are all higher codepoints, such as 你好'))
'ASCII is not changed, Latin-1 (\xe5\xe9\xee\xf8\xfc) is, as are all higher codepoints, such as \u4f60\u597d'

如果您必须拥有\uhhhh所有内容,那么您必须自行转换:

import re

def escape_unicode(t, _p=re.compile(r'[\u0080-\U0010ffff]')):
    def escape(match):
        char = ord(match.group())
        return '\\u{:04x}'.format(char) if char < 0x10000 else '\\U{:08x}'.format(char)
    return _p.sub(escape, t)

以上函数添加ascii()函数的引号:

>>> print(escape_unicode('你好'))
\u4f60\u597d
>>> print(escape_unicode('ASCII is not changed, Latin-1 (åéîøü) is, as are all higher codepoints, such as 你好'))
ASCII is not changed, Latin-1 (\u00e5\u00e9\u00ee\u00f8\u00fc) is, as are all higher codepoints, such as \u4f60\u597d

答案 1 :(得分:2)

请注意,如果不将\替换为\\,您想要的是不可逆的;例如。你不能知道实际的字符串是'好'(一个字符)还是'\\u597d'(ascii范围内的6个字符),因为两者都会产生\u597d作为输出。 Martijn的建议是反斜杠替换,并且是可逆的。

你可以自己进行转换:

def unicodeescape(s):
    return ''.join(c if ord(c) < 128 else '\\u%04x' % ord(c) for c in s)

print(unicodeescape('你好'))

(Martijn关于BMP之外的人物的说明仍然适用)

如果您想对程序输出的所有内容执行此操作,并且尝试记住通过转换函数传递所有内容并不像您想要的那样好,那么您也可以尝试这样的事情:

import codecs, sys

def unicodeescapereplace(error):
    if isinstance(error, UnicodeEncodeError):
        s = error.object[error.start:error.end]
        repl = ''.join('\\u%04x' % ord(c) for c in s)
        return (repl, error.end)
    raise error

codecs.register_error('unicodeescapereplace', unicodeescapereplace)
sys.stdout = codecs.getwriter('ascii')(sys.stdout.buffer, 'unicodeescapereplace')

print('你好')

这会创建一个自定义编码错误处理程序,它通过用unicode转义替换有问题的字符来处理UnicodeEncodeErrors。您可以像'你好'.encode('ascii', 'unicodeescapereplace')一样使用它,或者像上面的示例一样,将stdout替换为自动将其用于所有编码的stdout。

答案 2 :(得分:1)

正常表示是使用ascii内置函数获得的,作为Martijn Pieters的解释。

如果你真的想要继续打印\ u escapes,你可以手动

t = 'ASCII is not changed, Latin-1 (åéîøü) is, as are all higher codepoints, such as 你好'
disp = u = "'" + ''.join([c if (ord(c) < 128) else r'\u%04x' % (ord(c),) for c in t ]) + "'"
print(disp)
print(eval(disp))

按预期给出:

'ASCII is not changed, Latin-1 (\u00e5\u00e9\u00ee\u00f8\u00fc) is, as are all higher codepoints, such as \u4f60\u597d'
ASCII is not changed, Latin-1 (åéîøü) is, as are all higher codepoints, such as 你好

注意:我确实知道eval是邪恶的但是在那个特定的用例中我知道内部字符串不包含'并且它被包含在'中所以它不能超过仅仅转换编码字符 - 但我绝不会在外部字符串上执行此操作而不至少测试t.contains("'") ...

NB2:此方法无法正确处理代码大于0xffff的字符 - 如果没有其他 ...