Python 3,pythonic方式获取字节的字符串文字表示?

时间:2014-01-09 14:37:49

标签: python python-3.x

similiar question,但解决方案似乎不起作用。

说我编码了一个字符串:

>>> a = 'dada大大'.encode('utf-8')
>>> type(a)
<class 'bytes'>
>>> a
>>> b'dada\xe5\xa4\xa7\xe5\xa4\xa7'

我想要的是这样的:

dada\xe5\xa4\xa7\xe5\xa4\xa7

str(a)不起作用:

>>> str(a)
>>> "b'dada\\xe5\\xa4\\xa7\\xe5\\xa4\\xa7'"

我已经尝试将stdout重定向到变量,但我仍然得到了"b'dada\\xe5\\xa4\\xa7\\xe5\\xa4\\xa7'"

我可以使用正则表达式处理它并得到我想要的东西,但我正在寻找一种更加pythonic的方式来做到这一点。有什么建议吗?

3 个答案:

答案 0 :(得分:5)

由于您很高兴在评论中提及您的实际问题,我会再次更新我的答案以实际回应。原始答案可以在下面看到。

  

这是我发给Github Markdown API的字符串。这是可以接受unicode字符的唯一方法。我得到了带有原始字符dada大大

的渲染html

GitHub Markdown API要求您以JSON格式发送数据。 JSON本身借用了从JavaScript转义的字符串,对于这个字符,它将是\u5927。但是,当使用json module时,您根本不需要担心:

from urllib import urlopen
import json

text = 'dada大大'
data = json.dumps({ mode: 'markdown', 'text': text }).encode()
r = urlopen('https://api.github.com/markdown', data)

print(r.read().decode()) # <p>dada大大</p>

正如您所看到的,API可以毫无问题地接受编码文本并正确生成正确的输出,而无需担心编码。

或者将原始API与requests库一起使用时:

h = { 'Content-Type': 'text/plain' }
r = requests.post('https://api.github.com/markdown/raw', text.encode(), headers=h)

print(r.content.decode()) # <p>dada大大</p>

原始答案

>>> a = 'dada大大'.encode('utf-8')
>>> a
b'dada\xe5\xa4\xa7\xe5\xa4\xa7'
>>> str(a)
"b'dada\\xe5\\xa4\\xa7\\xe5\\xa4\\xa7'"
>>> str(a)[2:-1]
'dada\\xe5\\xa4\\xa7\\xe5\\xa4\\xa7'
>>> print(_)
dada\xe5\xa4\xa7\xe5\xa4\xa7

当您执行str(a)时,您将获得字节字符串的字符串表示形式。当然,当您在解释器中使用它时,解释器实际上会在其上调用repr来显示它。包含反斜杠的字符串会将它们转义为\\。这就是那些人来自的地方。

最后,您必须删除b'和尾随'以获取字节字符串的字符串表示形式的内容。

旁注:str()repr()在字节对象上使用时会产生相同的结果。


  

根据Poke的回答,我需要的是阻止repr的自动转义。

不,你没有。最终字符串中没有双反斜杠。它们只出现,因为当您在REPL中输入内容时,它会在调用repr之后将返回值输出到控制台。但这并不意味着,实际的字符串突然改变了:

>>> s = str(a)[2:-1]
>>> len(s)
28
>>> list(s)
['d', 'a', 'd', 'a', '\\', 'x', 'e', '5', '\\', 'x', 'a', '4', '\\', 'x', 'a', '7', '\\', 'x', 'e', '5', '\\', 'x', 'a', '4', '\\', 'x', 'a', '7']

如您所见,字符串中没有双反斜杠。是的,你可以再次看到它们,但这只是因为REPL打印了list(s)的返回值。列表中的每个项目都是单个字符,包括反斜杠。它们只是再次转义,因为'\'不是有效的字符串。

>>> '\'
SyntaxError: EOL while scanning string literal
>>> '\\'
'\\'
>>> len('\\')
1

答案 1 :(得分:4)

bytes实际上是一个整数数组:

>>> a = 'dada大大'.encode() # 'utf-8' by default
>>> list(a)
[100, 97, 100, 97, 229, 164, 167, 229, 164, 167]

您可以使用

获取每个的十六进制值
>>> list(map(hex, a))
['0x64', '0x61', '0x64', '0x61', '0xe5', '0xa4', '0xa7', '0xe5', '0xa4', '0xa7']

因此

>>> list(chr(x) if x < 128 else hex(x) for x in a)
['d', 'a', 'd', 'a', '0xe5', '0xa4', '0xa7', '0xe5', '0xa4', '0xa7']

>>> print("".join(chr(x) if x < 128 else hex(x).replace("0", "\\") for x in a))
dada\xe5\xa4\xa7\xe5\xa4\xa7

答案 2 :(得分:0)

好的,最后我找到了解决方案,它来自Python Replace \\ with \

a = 'dada大大'.encode('utf-8')
b = str(a)[2:-1].encode('utf-8').decode('unicode_escape')

也许我应该解释一下我想要的更清楚。

编辑 - 我的测试结果

>>> import requests
>>> text = 'dada大大'
>>> h = {'Content-Type': 'text/plain'}
>>> r = requests.post('https://api.github.com/markdown/raw', text.encode(), headers=h)
>>> print(r.content.decode())
{"message":"Invalid request media type (expecting 'text/plain')","documentation_url":"http://developer.github.com/v3/markdown/#render-a-markdown-document-in-raw-mode"}
>>> print(r.content.decode('utf-8'))
{"message":"Invalid request media type (expecting 'text/plain')","documentation_url":"http://developer.github.com/v3/markdown/#render-a-markdown-document-in-raw-mode"}
>>> r = requests.post('https://api.github.com/markdown/raw', text.encode('utf-8'), headers=h)
>>> print(r.content.decode('utf-8'))
{"message":"Invalid request media type (expecting 'text/plain')","documentation_url":"http://developer.github.com/v3/markdown/#render-a-markdown-document-in-raw-mode"}