我正在努力: 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?
感谢阅读,感谢您的帮助。
答案 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可以使代码更简单 - 而且效率更高,这是一个很好的奖励。)