簡體   English   中英

Python 3,獲取字符串的字符串文字表示形式的pythonic方法?

[英]Python 3, pythonic way to get the string literal representation of bytes?

有一個類似的問題 ,但是解決方案似乎不起作用。

假設我已經編碼了一個字符串:

>>> 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的方式來做到這一點。 有什么建議么?

由於您很樂意在評論中提及您的實際問題 ,因此我將再次更新我的答案以實際回答。 原始答案可以在下面看到。

這是我發布到Github Markdown API的字符串。 這是可以接受unicode字符的唯一方法。 我得到了帶有原始字符dada大大的渲染html

GitHub Markdown API要求您將數據作為JSON發送。 JSON本身借用了從JavaScript轉義的字符串,該字符為\大 但是,當使用json模塊時,您完全不需要擔心:

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可以毫無問題地接受編碼后的文本,並且可以正確生成正確的輸出,而不必擔心編碼。

或在requests庫中使用原始API時:

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

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

好的,最后我找到了解決方案,它來自Python用\\替換\\\\

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"}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM