如何清理兼容 Python 2.7 + 3 的包,使它们只兼容 Python 3.6?
How to clean packages compatible Python 2.7 + 3 to make them only Python 3.6 compatible?
对于某些项目,我想停止支持 Python 2.7(参见 http://python3statement.org/)以仅使用 Python > 3.6(或者更确切地说是 3.5 + f-string,例如Pypy v6.0).
第一步可能是修改 setup.py 文件,如果尝试使用没有 f-string 的 Python 版本的包,则会出现显式错误。
但是切换到纯 Python 3.6 语法并删除所有
需要做很多工作
并在许多地方进行替换
class MyClass(object)
-> class MyClass:
super(MyClass, self)
-> super()
"{}".format(foo)
-> f"{foo}"
我基本上是手动为代码完成这项工作(实际上我还通过使用 Python 脚本处理代码来自动执行一些步骤),我真的看到了不同之处。代码现在不那么冗长,而且全局更漂亮。
我敢肯定我忘记了很多其他可以做的很好的简化,例如我现在使用了很多 from pathlib import Path
但这些更改不那么直接。
如何将 Python 2.7/3.6 兼容代码转换为干净的 Python 3.6 代码?如何避免手动完成这项无聊的工作?
在
之后编辑
我认为假设的内化(在许多情况下不会追加)不应阻止我们使用 f 弦,它只是更干净(而且速度稍快)。
我仍然认为我提到的修改是合理的。
如果您的目标是在 Python-3.6 之前的 运行 停止您的代码,请明确检查:
import sys
if sys.version_info < (3, 6):
raise RuntimeError('my_thing requires a Python version of at least 3.6.')
如果您只是不再关心 Python-3.6 之前的支持,那么您无需执行任何操作。您的代码已经完全有效 Python 3.6.
尝试遍历整个代码库并将其全部转换为使用不适用于先前版本的技术只会导致大量不必要的代码改动,并冒着引入错误的风险而没有真正的好处。新技术甚至不是对旧技术的无条件升级;例如,如果您将所有字符串格式转换为 f 字符串,您可能会发现自己无论如何都必须重新转换所有内容以支持国际化,因为不可能将 f 字符串格式国际化。
相反,当您有 特定原因 更改代码的某些部分时,您应该随意使用与 3.6 之前版本不兼容的技术 Python进行这些更改时发布。
请记住,新 Python 版本中的新内容不仅仅是像 0 参数 super
这样的简单内容。如果你出于某种原因想要让你的代码充满尽可能多的闪亮的新语言特性,那么有像
这样的东西
- 将魔法常量切换为
enum
、
- 每样东西都贴 type annotations,
- 切换到
pathlib
进行路径操作,
- 切换到新的
subprocess.run
API,
- 用
yield from
或 重构你的生成器
- 使用新的 I/O exception hierarchy、
这还没有考虑 Python 您现在可以访问的仅 3 项依赖项。许多这些东西需要仔细的设计工作才能合并到您的程序中。以产生实际上好的 代码的方式合并它们不是自动工具或无意识的快速手动传递代码可以处理的。试图告诉您如何将所有这些东西合并到您的程序中对于 Stack Overflow 的答案来说太宽泛了;新东西太多了。
此外,甚至 Python 标准库本身也没有努力清除与旧版本兼容的模式的使用。快速 grep
到 current CPython master branch 显示数百个 类 仍然继承自 object
和超过一千个可以用 f-strings 替换的 str.format
的使用。
我找到了一个很棒的工具,它可以满足我的需要:pyupgrade。
有一个选项 --py36-plus
触发大多数 "{}".format(var)
被 f"{var}"
替换(更清晰)。
使用 Unix 命令 find -name "*.py" | xargs pyupgrade --py36-plus
它会产生这样的提交:
https://bitbucket.org/fluiddyn/fluidsim/pull-requests/78/pyupgrade-py36-plus
现在,代码更加清晰明了,展示了我们今天想要的编码风格。
它对于放弃 Python 2.7 支持的项目非常有用(参见 http://python3statement.org/)。
对于某些项目,我想停止支持 Python 2.7(参见 http://python3statement.org/)以仅使用 Python > 3.6(或者更确切地说是 3.5 + f-string,例如Pypy v6.0).
第一步可能是修改 setup.py 文件,如果尝试使用没有 f-string 的 Python 版本的包,则会出现显式错误。
但是切换到纯 Python 3.6 语法并删除所有
需要做很多工作并在许多地方进行替换
class MyClass(object)
->class MyClass:
super(MyClass, self)
->super()
"{}".format(foo)
->f"{foo}"
我基本上是手动为代码完成这项工作(实际上我还通过使用 Python 脚本处理代码来自动执行一些步骤),我真的看到了不同之处。代码现在不那么冗长,而且全局更漂亮。
我敢肯定我忘记了很多其他可以做的很好的简化,例如我现在使用了很多 from pathlib import Path
但这些更改不那么直接。
如何将 Python 2.7/3.6 兼容代码转换为干净的 Python 3.6 代码?如何避免手动完成这项无聊的工作?
在
之后编辑
我认为假设的内化(在许多情况下不会追加)不应阻止我们使用 f 弦,它只是更干净(而且速度稍快)。
我仍然认为我提到的修改是合理的。
如果您的目标是在 Python-3.6 之前的 运行 停止您的代码,请明确检查:
import sys
if sys.version_info < (3, 6):
raise RuntimeError('my_thing requires a Python version of at least 3.6.')
如果您只是不再关心 Python-3.6 之前的支持,那么您无需执行任何操作。您的代码已经完全有效 Python 3.6.
尝试遍历整个代码库并将其全部转换为使用不适用于先前版本的技术只会导致大量不必要的代码改动,并冒着引入错误的风险而没有真正的好处。新技术甚至不是对旧技术的无条件升级;例如,如果您将所有字符串格式转换为 f 字符串,您可能会发现自己无论如何都必须重新转换所有内容以支持国际化,因为不可能将 f 字符串格式国际化。
相反,当您有 特定原因 更改代码的某些部分时,您应该随意使用与 3.6 之前版本不兼容的技术 Python进行这些更改时发布。
请记住,新 Python 版本中的新内容不仅仅是像 0 参数 super
这样的简单内容。如果你出于某种原因想要让你的代码充满尽可能多的闪亮的新语言特性,那么有像
- 将魔法常量切换为
enum
、 - 每样东西都贴 type annotations,
- 切换到
pathlib
进行路径操作, - 切换到新的
subprocess.run
API, - 用
yield from
或 重构你的生成器
- 使用新的 I/O exception hierarchy、
这还没有考虑 Python 您现在可以访问的仅 3 项依赖项。许多这些东西需要仔细的设计工作才能合并到您的程序中。以产生实际上好的 代码的方式合并它们不是自动工具或无意识的快速手动传递代码可以处理的。试图告诉您如何将所有这些东西合并到您的程序中对于 Stack Overflow 的答案来说太宽泛了;新东西太多了。
此外,甚至 Python 标准库本身也没有努力清除与旧版本兼容的模式的使用。快速 grep
到 current CPython master branch 显示数百个 类 仍然继承自 object
和超过一千个可以用 f-strings 替换的 str.format
的使用。
我找到了一个很棒的工具,它可以满足我的需要:pyupgrade。
有一个选项 --py36-plus
触发大多数 "{}".format(var)
被 f"{var}"
替换(更清晰)。
使用 Unix 命令 find -name "*.py" | xargs pyupgrade --py36-plus
它会产生这样的提交:
https://bitbucket.org/fluiddyn/fluidsim/pull-requests/78/pyupgrade-py36-plus
现在,代码更加清晰明了,展示了我们今天想要的编码风格。
它对于放弃 Python 2.7 支持的项目非常有用(参见 http://python3statement.org/)。