类似于字节的对象是必需的/ ord()期望的字符串,长度为1,但是找到了int(python 3.6)

时间:2018-05-01 04:28:31

标签: python encryption ord

我正在努力: softScheck/tplink-smartplug

我陷入了错误的循环中。第一个的修复,导致另一个,另一个的修复,导致第一个。代码全部位于git链接的tplink-smartplug.py中。

cmd = "{\"system\":{\"set_relay_state\":{\"state\":0}}}"

sock_tcp.send(encrypt(cmd))

def encrypt(string):
    key = 171
    result = "\0\0\0\0"
    for i in string: 
        a = key ^ ord(i)
        key = a
        result += chr(a)
    return result

实际上,结果='Ðòøÿ÷Õï¶ÅÔùðè·Ä°Ñ¥ÀâØ£òçöÔîÞ£Þ'我得到错误(在原始文件的第92行:sock_tcp.send(encrypt(cmd)):

  

需要类似字节的对象,而不是'str'

所以我也改变了函数调用:

sock_tcp.send(encrypt(cmd.encode('utf-8')))

我的错误也发生了变化:

  

ord()期望的字符串长度为1,但是找到了int

我理解ord()正在尝试做什么,我理解编码。但我不明白的是......如果我不能给编译器它想要的东西,我该如何将这个加密的消息发送到我的智能插件?有工作吗?我很确定原始的git是用Python 2或更早版本编写的。那么也许我没有正确转换为Python 3?

感谢阅读,感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

在Python 2中,encode的结果是str字节字符串,它是一个1字节str值的序列。因此,当您执行for i in string:时,每个i都是str,您必须致电ord(i)将其转换为0到255之间的数字。

在Python 3中,encode的结果是bytes字节字符串,它是一个1字节整数的序列。因此,当您执行for i in string:时,每个i已经是int,从0到255,所以您不必做任何事情来转换它。 (而且,无论如何,如果你尝试这样做,你将会得到你TypeError看到的。{/ p>

与此同时,您将result建立为str。在Python 2中,这很好,但在Python 3中,这意味着它是Unicode,而不是字节。因此,您正在看到的其他TypeError

有关如何将Python 2字符串处理代码移植到Python 3的更多详细信息,您应该阅读“移植指南”,尤其是Text versus binary data,如果您需要更多背景知识,可以阅读Unicode HOWTO

为Python 2和3编写代码以同样方式工作的一种方法是对两个值使用bytearray

def encrypt(string):
    key = 171
    result = bytearray(b"\0\0\0\0")
    for i in bytearray(string): 
        a = key ^ i
        key = a
        result.append(a)
    return result

cmd = u"{\"system\":{\"set_relay_state\":{\"state\":0}}}"

sock_tcp.send(encrypt(cmd.encode('utf-8')))

注意u上的cmd前缀,即使在Python 2中也确保它是Unicode,在b上确保result前缀,这可以确保它甚至在Python 3中都是字节。虽然你知道cmd是纯ASCII,但这样做可能更简单:

cmd = b"{\"system\":{\"set_relay_state\":{\"state\":0}}}"

sock_tcp.send(encrypt(cmd))

如果您不关心Python 2,则只需for i in string:而不将其转换为bytearray,但您仍可能希望将result用于append。 (能够Field直接使用int可以使代码更简单 - 而且效率更高,这是一个很好的奖励。)