В 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 - использовать 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
, который гарантирует, что это Unicode даже в Python 2, и префикс 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
int напрямую к нему делает более простой код - и это еще более эффективно, как приятный бонус.)