Python:如何在Python3中通过套接字发送十六进制字符串而不进行编码?

时间:2017-04-17 12:12:05

标签: python python-3.x unicode

我在python2中执行了socket通信,它运行良好,我必须让它再次在python3中运行。我已经厌倦了很多格式的str.encode()东西,但网络的另一面无法识别我发送的内容。我唯一知道的是python3 str类型默认编码为Unicode uft-8,我很确定这里的关键问题是python2 str类型的格式是什么。我必须发送与python2 str中存储的内容完全相同的内容。但棘手的是python3的套接字只发送编码的unicode字节或其他缓冲区接口,而不是带有Python2中原始数据的str类型。示例如下:

在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?

任何人都可以帮我吗?

4 个答案:

答案 0 :(得分: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以供参考。

答案 1 :(得分: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'

答案 2 :(得分:1)

  

我在python2中执行了socket通信,它运行良好,我必须让它再次在python3中运行。我已经厌倦了很多格式的str.encode()东西,但是网络的另一面无法识别我发送的内容。

您必须确保您发送的任何内容都可由另一方解码。您需要采取的第一步是了解网络/文件/套接字使用的编码类型。例如,如果您使用UTF-8发送编码数据并且客户端具有ASCII编码,则这将起作用。但是,假设cp500是您的客户端的编码方案,并且您将编码的字符串发送为UTF-8,这不会起作用。最好将所需编码的名称明确地传递给函数,因为有时您的平台的默认编码可能不一定是UTF-8。您始终可以通过此次调用sys.getdefaultencoding()检查默认编码。

  

我唯一知道的是python3 str类型默认编码为Unicode uft-8,我很确定这里的关键问题是python2 str类型的格式是什么。我必须发送与python2 str中存储的内容完全相同的内容。但棘手的是python3的套接字只发送编码的unicode字节或其他缓冲区接口,而不是带有Python2中原始数据的str类型

是的,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可能是您的客户使用的编码。

答案 3 :(得分: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'