python - Python 2 到 3 迁移过程 - 关于 Unicode 的差异
问题描述
我正在尝试将我的代码从 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'
如您所见,在 Python2Out[3]
中与 相比具有不同的值Out[5]
,而在 Python3Out[4]
中Out[6]
则相同。
有没有办法重现Out[5]
Python2 代码段中显示的值?
作为迁移过程的一部分,我需要确保相同的输入产生相同的输出,因此我不会在数据库中插入新记录,而是更新现有记录。
解决方案
使用str()
输出的十六进制摘要是问题所在。 str()
是一个与版本相关的字符串,您需要完全相同的表示形式来形成十六进制摘要:
蟒蛇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'
推荐阅读
- spring-boot - Spring数据jdbc错误BadSqlGrammarException: PreparedStatementCallback; 糟糕的 SQL 语法,同时尝试保存简单的聚合
- react-testing-library - React 测试库 getByRole('heading') 如何获取具有特定标题级别的节点
- c++ - 多个.cu、.h和.c文件之间的Nsight CUDA链接问题
- python - 为什么 cv2.Sobel 函数返回黑白图像而不是灰度图像
- c - 编程 C - fscanf () 不读取整个日期,它只读取“1 8 2020”而不是“01 08 2020”
- sql-server - 什么是增量文件和完整文件的概念?
- powershell - 从 powershell 运行 msi 时指定完整安装选项
- python - Python - 更改函数参数,即使它是全局的
- e2e-testing - 如何改善使用 codeceptjs 进行端到端测试的时间?
- javascript - 只允许用户输入时间格式