首页 > 解决方案 > 需要类似字节的对象 / ord() 预期的长度为 1 的字符串,但找到了 int (python 3.6)

问题描述

我正在尝试使用: 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?

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

标签: pythonencryptionord

解决方案


在 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你所看到的。)

同时,您正在建立result一个str. 在 Python 2 中,这很好,但在 Python 3 中,这意味着它是 Unicode,而不是字节。因此,TypeError您看到的另一个。

有关如何将 Python 2 字符串处理代码移植到 Python 3 的更多详细信息,您应该阅读移植指南,尤其是文本与二进制数据,如果您需要更多背景知识,可能还需要阅读Unicode HOWTO 。


您可以编写代码以在 Python 2 和 3 中以相同方式工作的一种方法是将 abytearray用于两个值:

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前缀 on cmd,它确保它即使在 Python 2 中也是 Unicode,而b前缀 on result,它确保它即使在 Python 3 中也是字节。虽然你知道cmd它是纯 ASCII,但这样做可能更简单:

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

sock_tcp.send(encrypt(cmd))

如果您不关心 Python 2,您可以只 forfor i in string:而不将其转换为 a bytearray,但您可能仍想使用一个 for result。(能够append直接对它进行 int 处理可以简化代码——而且它甚至更高效,这是一个很好的奖励。)


推荐阅读