2017-04-17 87 views
0

我在python2中執行套接字通信,它運行良好,我必須使它再次在python3中工作。我有很多格式的str.encode(),但網絡的另一端無法識別我發送的內容。我唯一知道的是,python3 str類型在默認情況下被編碼爲Unicode uft-8,我很確定這裏的關鍵問題是python2 str類型的格式是什麼。我必須發送與python2 str中存儲的內容完全相同的內容。但棘手的是python3的套接字只發送編碼的unicode字節或其他緩衝區接口,而不是str2類型與Python2中的原始數據。這個例子是如下:Python:如何通過Python3中的套接字發送十六進制字符串而不對其進行編碼?

在python2:

data = 'AA060100B155' 
datasplit = [fulldata[i: i+2] for i in range(0, len(fulldata), 2)] 
senddata = '' 
for item in datasplit: 
    itemdec = chr(int(item, 16)) 
    senddata += itemdec 
print(senddata) 
#'\xaa\x06\x01\x00\xb1U',which is the data I need 

在python3,似乎它只能通過發送編碼的字節「senddata.encode()」,但它不是我想要的格式。你可以試試:

print(senddata.encode('latin-1')) 
#b'\xaa\x06\x01\x01\xb2U' 

到看到兩個senddatas的差異,一個有趣的事情是,它是錯誤的編碼使用UTF-8時。

存儲在Python3 str類型的數據是我需要的東西,但我的問題是如何發送該字符串的數據而不編碼它?或者如何在Python3中執行相同的str2類型的Python2?

任何人都可以幫助我嗎?

+0

哪裏''ª\ X06 \ X01 \x01²U''從何而來?當我運行你的代碼(在Python 2.6.6中)時,'senddata'的'repr'是''\ xaa \ x06 \ x01 \ x00 \ xb1U''。 –

+0

對不起,是從python3的IDE。對不起,迷惑你 – lwangreen

回答

1

我進行socket通信輸出在python2中,它工作得很好,我哈哈讓它再次在python3中工作。我有很多格式的str.encode(),但網絡的另一端無法識別我發送的內容。

你必須確保你發送的任何東西都可以被另一方解碼。您需要採取的第一步是瞭解網絡/文件/套接字使用的編碼類型。如果你使用UTF-8來發送你的編碼數據,並且客戶端使用ASCII編碼,這將起作用。但是,說cp500是你的客戶端的編碼方案,你發送的編碼字符串爲UTF-8,這是行不通的。將所需編碼的名稱明確地傳遞給函數會更好,因爲有時平臺的默認編碼可能不一定是UTF-8。您可以隨時通過此呼叫sys.getdefaultencoding()檢查默認編碼。

我知道的唯一的事情是,python3 STR類型編碼爲Unicode UFT-8在默認情況下,我敢肯定,在這裏關鍵的問題是,什麼是python2 STR型的格式。我必須發送與python2 str中存儲的內容完全相同的內容。但棘手的事情是python3的插座只發送編碼的Unicode字節或其它緩衝器接口,而不是與原始數據的STR類型在Python2

是,Python的3.X使用UTF-8作爲默認編碼,但在某些情況下不能保證默認編碼可以改變,最好是明確傳遞所需編碼的名稱以避免出現這種情況。但請注意,Python 3.X中的str與2.X中的unicode + str等效,但2.X中的str僅支持 8位(1字節)(0-255)個字符。

一方面,你的問題似乎與3.X及其類型區分strbytes字符串之間。對於期望bytes將於今日3.X版本中不接受str的API。這不像2.X,你可以自由混合unicodestr。在3.X中的這種區別是有意義的,因爲str代表已解碼的字符串並用於文本數據。而bytes將編碼的字符串表示爲具有絕對字節值的原始字節。

另一方面,您在3.X中爲您的文本選擇正確的編碼時需要傳遞給客戶端時遇到問題。首先檢查你的客戶使用什麼類型的編碼。其次,將編碼後的字符串與客戶端的正確編碼方案一起傳遞,以便客戶端可以正確解碼:str.encode('same-encoding-as-client')

由於您在2.X中傳遞的數據爲str,並且工作正常,所以我懷疑它很可能是您的客戶端使用8位字符編碼,類似Latin-1可能是您的客戶端使用的編碼。

+0

感謝您的長時間解釋!我會和客戶談談。 – lwangreen

+0

@Iwangreen另請參閱:[Unicode HOWTO](https://docs.python.org/3.3/howto/unicode.html)。 – direprobs

+0

好的,我有一個問題。是否有Python2的默認編碼方案?從你的答案我認爲這是一個不適合。實際上,我們通過Python應用程序執行硬件控制,並且在電路板上也可能沒有編碼方案。這可能是我可以與Python2 str進行通信而不是Python3進行通信的原因。你的意見? – lwangreen

2

可以整個字符串轉換爲整數,則使用整數方法to_bytes將其轉換成一個bytes對象:

fulldata = 'AA060100B155' 

senddata = int(fulldata, 16).to_bytes(len(fulldata)//2, byteorder='big') 
print(senddata) 

# b'\xaa\x06\x01\x00\xb1U' 

to_bytes第一個參數是字節數,第二個(必需)是字節順序。 參見int.to_bytes的官方文檔以供參考。

+0

感謝您的回覆,但它不能解決我的問題。無論如何感謝 – lwangreen

+0

你只需要發送它,就像你之前發送Python2'str'的​​方式一樣。 –

2

有多種方法可以做到這一點。這裏有一個,在這兩個的Python 2和Python 3

from binascii import unhexlify 

fulldata = 'AA060100B155' 
senddata = unhexlify(fulldata) 
print(repr(senddata)) 

工作的Python 2輸出

'\xaa\x06\x01\x00\xb1U' 

的Python 3

b'\xaa\x06\x01\x00\xb1U' 
+0

這不是關於我發送的內容,而是關於另一方可以識別的內容。你知道'\ xaa \ x06 \ x01 \ x00 \ xb1U'和它前面的'b'有什麼區別嗎? – lwangreen

+0

@lwangreen在Python 2中,沒有任何區別。在Python 3中,'b'\ xaa \ x06 \ x01 \ x00 \ xb1U''是一個字節字符串,包含_exactly_與Python 2的'b'\ xaa \ x06 \ x01 \ x00 \ xb1U''相同的字節或' \的Xaa \ X06 \ X01 \ X00 \ xb1U''。但是,Python 3中的'\ xaa \ x06 \ x01 \ x00 \ xb1U''與'u'\ xaa \ x06 \ x01 \ x00 \ xb1U'(在Python 2或Python 3中)是一樣的。你可以使用'u'\ xaa \ x06 \ x01 \ x00 \ xb1U'.encode('latin-1')'將其轉換爲以前的字節串。這是因爲Latin-1是Unicode的一個子集。 –

+1

@lwangreen使用'fulldata ='AA060100B155''您的Python 2代碼發送''\ xaa \ x06 \ x01 \ x00 \ xb1U'。因此,如果您的Python 3代碼通過套接字發送字節字符串'b'\ xaa \ x06 \ x01 \ x00 \ xb1U'',它們將獲得_exactly_相同的字節。 –

0

以下是Python 2/3兼容。 unhexlify函數將十六進制符號轉換爲字節。使用一個字節字符串,你不必處理Unicode字符串。 Python 2在默認情況下是字節字符串,但是識別Python 3需要使用字節字符串的語法b''

from binascii import unhexlify 
fulldata = b'AA060100B155' 
print(repr(unhexlify(fulldata))) 

的Python 2輸出:

'\xaa\x06\x01\x00\xb1U' 

Python 3的輸出:

b'\xaa\x06\x01\x00\xb1U' 
相關問題