我正在尝试将代码从Python2迁移到Python3,因为不再支持Python2。但是,由于两个版本之间的差异,我在迁移过程中遇到了困难。我知道Python2曾经同时具有字符串和unicode对象,而Python3默认存储的字符串是unicode。
在我的代码中的某个地方,我将元组的十六进制表示形式存储在数据库中。我从用户填写的表单中获取此元组,其中一个值是unicode类型。由于Python3在字符串和Unicode之间没有区别,我最终得到了包含相同值的元组的不同十六进制表示形式。
这是显示我的问题的代码段:
Python2-
In [1]: from hashlib import sha1
In [2]: cred = ('user', 'pass')
In [3]: sha1(str(cred)).hexdigest()
Out[3]: '7cd99ee437e8166559f55a0336d4b48d9bc62bb2'
In [4]: unicode_cred = ('user', u'pass')
In [5]: sha1(str(unicode_cred)).hexdigest()
Out[5]: '807a138ff9b0dd6ce6a937e3df3bba3223b40fcd'
Python3-
In [1]: from hashlib import sha1
In [2]: cred = ('user', 'pass')
In [3]: sha1(str(cred)).hexdigest()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-847e91fdf4c5> in <module>
----> 1 sha1(str(cred)).hexdigest()
TypeError: Unicode-objects must be encoded before hashing
In [4]: sha1(str(cred).encode('utf-8')).hexdigest()
Out[4]: '7cd99ee437e8166559f55a0336d4b48d9bc62bb2'
In [5]: unicode_cred = ('user', u'pass')
In [6]: sha1(str(unicode_cred).encode('utf-8')).hexdigest()
Out[6]: '7cd99ee437e8166559f55a0336d4b48d9bc62bb2'
您可以看到,在Python2中,Out[3]
与Out[5]
的值不同,而在Python3中,Out[4]
和Out[6]
相同。
是否有一种方法可以再现Out[5]
的值,如Python2片段所示?在迁移过程中,我需要确保相同的输入产生相同的输出,因此我不会在数据库中插入新记录,而不会更新现有记录。
使用str()
输出的十六进制摘要是问题。 str()
是一个与版本有关的字符串,您需要完全相同的表示形式来形成十六进制摘要:
Python 2
>>> unicode_cred = ('user', u'pass')
>>> str(unicode_cred)
"('user', u'pass')"
Python 3(请注意缺少的'u')。 str()
的输出也是Python 3上的Unicode字符串,因此必须将其编码为字节才能与sha1()
一起使用。 b
不是字符串的一部分,仅表示它现在是字节字符串。
>>> unicode_cred = ('user', u'pass')
>>> str(unicode_cred).encode('utf-8')
b"('user', 'pass')"
您需要与u
组成相同的字符串以获取相同的摘要,这有点难看。在这里,我使用f字符串自定义格式为u
的元组。我还使用ascii
进行编码,因为非ASCII字符会引起其他问题。希望您没有非ASCII的用户名和密码。
>>> from hashlib import sha1
>>> unicode_cred = ('user', u'pass')
>>> f"('{unicode_cred[0]}', u'{unicode_cred[1]}')"
"('user', u'pass')"
>>> sha1(f"('{unicode_cred[0]}', u'{unicode_cred[1]}')".encode('ascii')).hexdigest()
'807a138ff9b0dd6ce6a937e3df3bba3223b40fcd'