【问题标题】:Python2 version of this python3 code for encoding这个python3代码的python2版本进行编码
【发布时间】:2017-12-07 13:54:52
【问题描述】:

我正在尝试使用 python2 版本 2.7.13 从this post(与 python3 版本 3.5.3 完美配合)中的答案运行代码:

def myencode_str(ori_str, key):
    enc = []
    for i in range(len(ori_str)):
        key_c = key[i % len(key)]
        enc_c = (ord(ori_str[i]) + ord(key_c)) % 256
        enc.append(enc_c)
    return (base64.urlsafe_b64encode(bytes(enc))).decode("utf-8") 

我正在使用以下解码 fn:

def mydecode(enc_str, key):
    dec = []
    enc_str = base64.urlsafe_b64decode(enc_str)
    for i in range(len(enc_str)):
        key_c = key[i % len(key)]
        dec_c = chr((256 + enc_str[i] - ord(key_c)) % 256)
        dec.append(dec_c)
    return "".join(dec)

但我收到以下错误消息:

    dec_c = chr((256 + enc_str[i] - ord(key_c)) % 256)
TypeError: unsupported operand type(s) for +: 'int' and 'str'

我尝试了以下更改的代码,但它们也不起作用:

    dec_c = chr((256 + int(enc_str[i]) - int(ord(key_c))) % 256)
ValueError: invalid literal for int() with base 10: '\xc3'

问题出在哪里,如何解决?

【问题讨论】:

    标签: python python-3.x python-2.7 encoding


    【解决方案1】:

    问题在于bytes 构造函数在 Python2 和 Python3 之间发生了变化,当它接收到整数列表时:

    • 在 Python3 中,它构建一个字节字符串,其中每个字节从列表中接收一个代码
    • 在 Python2 中,它只是将列表转换为字符串(通过使用表示或字符串)

    而在 Python3 中,字节字符串是字节的可迭代对象(可直接转换为整数),而在 Python2 中它只是字符串。

    所以你的功能必须稍微改变一下:

    def myencode_str(ori_str, key):
        enc = []
        for i in range(len(ori_str)):
            key_c = key[i % len(key)]
            enc_c = (ord(ori_str[i]) + ord(key_c)) % 256
            enc.append(enc_c)
        return (base64.urlsafe_b64encode(''.join([chr(i) for i in enc])))
    
    def mydecode(enc_str, key):
        dec = []
        enc_str = [ord(i) for i in base64.urlsafe_b64decode(enc_str)]
        for i in range(len(enc_str)):
            key_c = key[i % len(key)]
            dec_c = chr((256 + enc_str[i] - ord(key_c)) % 256)
            dec.append(dec_c)
        return "".join(dec)
    

    事实上,在bytearray 类的帮助下,可以编写这些函数,以便在 Python2 和 Python3 中使用相同的代码,该类在两个版本中具有相同的行为。只需选择输入是字节字符串还是 Unicode 字符串。由于算法是基于字节的,我选择在以下代码中处理字节字符串。您需要对原始字符串和密钥进行编码(使用 'utf8' 以实现完全可移植性)并解码解码后的字符串以处理 unicode 字符串:

    def myencode_str(ori_str, key):
        enc = []
        b = bytearray(ori_str)
        k = bytearray(key)
        for i, c in enumerate(b):
            key_c = k[i % len(key)]
            enc_c = (c + key_c) % 256
            enc.append(enc_c)
        return (base64.urlsafe_b64encode(bytes(bytearray(enc))))
    
    def mydecode(enc_str, key):
        dec = []
        enc_str = bytearray(base64.urlsafe_b64decode(enc_str))
        k = bytearray(key)
        for i, c in enumerate(enc_str):
            key_c = k[i % len(key)]
            dec_c = (c - key_c) % 256
            dec.append(dec_c)
        return bytes(bytearray(dec))
    

    然后你可以在 Python2 中做:

    >>> myencode_str(b"abcdef", b"XYZ")
    'ubu9vL7A'
    >>> mydecode('ubu9vL7A', b"XYZ")
    'abcdef'
    

    在 Python3 中:

    >>> myencode_str(b"abcdef", b"XYZ")
    b'ubu9vL7A'
    >>> mydecode(b'ubu9vL7A', b"XYZ")
    b'abcdef'
    

    【讨论】:

    • 我可以使用什么同时适用于 python2 和 python3 以及编码版本可以存储在文本文件中的位置(不需要写入二进制文件)?
    • 我无法想象一种完全透明的方式,因为您正在处理在 Python2 和 Python3 中具有不同行为的字节。我知道在这里编写兼容代码的唯一方法是测试主要的 Python 版本。
    • @rnso:我终于想起了bytearray 类,它允许编写在 Python2 和 Python3 中工作的代码。查看我的上次编辑
    猜你喜欢
    • 2013-07-13
    • 2017-09-02
    • 1970-01-01
    • 2020-03-30
    • 2017-01-24
    • 2020-09-14
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    相关资源
    最近更新 更多