对于 Python2 到 Python3 的代码转换,哪个版本的 Python 和 Django 最适合?

Moo*_*oon 11 python django python-2to3 python-3.x

目前我在大公司工作,我们需要将 python2 旧的大 Django 项目转换为 python3 版本,所以我做了很多相关的研究,但仍然无法找到与哪个版本的 Python 和 Django 最适合转换相关的完美答案。

目前,我在旧版本中使用 Python:2.7.16 和 Django:1.9.13。

任何人都可以向我推荐最适合的 Python 和 Django 版本,用于 python2 到 python3 转换的旧版本。

JL *_*ret 5

我想我应该在 Wim 的答案所提倡的策略中添加一些内容- 首先让 Django 的适当版本同时运行在 2.7 和 3.x 上 - 并概述一些对我有用的 策略。

Python 2.7 是你的逃生舱,直到你扣动 3.x 的扳机

  • 你的测试应该在两者上运行
  • 不要使用任何 3.x 特定功能,例如 f-strings
  • 首先是 Python 3.x,然后是 Django 2.x,它不能在 2.7 上运行
  • 尽早开始,不要过度分析,但要避免大爆炸方法
    • 首先逐个文件。
    • 从最低级别的代码开始,例如您拥有测试套件的实用程序库。
    • 如果可能,请尝试逐步将更改合并到 2.7 生产分支,并使 3.x 移植代码与产品更改保持同步。

从 Django 的哪个小版本开始?

我的标准是 Django 迁移可以相当参与(实际上需要比 2=>3 工作更多的思考)。因此,我会转向最新、最好的 1.11,这样您就已经为 2.7 用户提供了一些价值。1.11 上可能有大量 2.x 之前的兼容性填充程序您将收到其 2.x 弃用警告。

从 Python 3.x 的哪个小版本开始?

最好考虑所有角度,例如第 3 方库的可用性、CI/devops 套件的支持以及所选服务器操作系统映像的可用性。例如,您始终可以安装 3.8 并尝试单独安装您的requirements.txt。

利用git(或您使用的任何 scm)和virtualenv

  • 单独的requirement.txt文件,但是...
  • 如果您有基于文件的 git 存储库,则可以使用pip install -e <your directory>. 这意味着,在 2 个不同的终端中,您可以针对相同的单元测试运行 2.7 和 3.x。
  • 你甚至可以在不同的端口上并行运行 2.7 和 3.x Django 服务器,并将 Firefox 和 Chrome 指向它们。
  • 经常提交(至少在移植分支上)并了解git bisect

利用2到3

是的,如果你允许的话,它会破坏 2.7 代码和 Django。所以...

  • 在预览模式下或针对单个文件运行它。看看它破坏了什么,但也看看它做对了什么。

  • 将其限制为仅某些不会破坏 2.7 或 Django 的转换。 print x=>print (x)except(Exception) as e是两个显而易见的事情。

这就是我的限制命令的样子:

2to3 $tgt -w -f except -f raise -f next -f funcattrs -f print
Run Code Online (Sandbox Code Playgroud)
  • 逐个文件运行它,直到您真正有信心为止。

使用sedawk而不是编辑器进行批量转换。

优点是,当您更加了解应用程序的具体问题时,您可以构建一套可以在一个文件或多个文件上运行的更改,并在不破坏 2.7 或 Django 的情况下完成大部分工作。在适当节流2to3次之后应用此方法。这使得您可以在编辑器中进行残留清理并让测试通过。

(可选)开始在 2.7 代码上运行黑色。

black 是一个代码格式化程序,使用 Python 3 AST 来运行其分析。它不会尝试运行代码,但会标记阻止其进入 AST 阶段的语法错误。不过,您将需要使用一些 pip install global 魔法才能到达那里,并且您必须相信黑色的有用性。

其他人已经做到了——向他们学习。

聆听#155 迁移到 Python 3 的实用步骤应该会给您一些关于这项工作的想法。查看它的显示链接。他们喜欢谈论 Instagram(?) 的举措,该举措涉及在公共代码库和同一个 git 分支上逐步调整运行 2.7 代码到 3.x 语法,直到触发日。

另请参阅保守的 Python 3 移植指南

Instagram 顺利迁移到 Python 3 - 新堆栈

结论

您到达 Django 1.11 EOL(2020 年 4 月)的时间相当短,因此如果您有 2 个以上的开发资源可以投入使用,我会考虑并行执行以下操作:

  • DEV#1:从 Django 1.11 开始(理论上 Django 1.11 可能最适合作为 Django 2.x 的起点),使用 2.7。

  • DEV#2:开始使用非 Django 实用程序代码的 Python 3.6/3.7。由于此时代码与 2.7 兼容,因此请将其合并到 #1 中。

了解这两项任务如何进行,评估 Django 相关项目的风险是什么以及 Python 3 的痛点是什么。您已经错过了 Python 2.7 EOL,但过时的 Web 框架可能比旧版 Python 2.7 更危险,至少在几个月内如此。因此,我不会等太久就开始从 Django 1.9 迁移,并且您所做的工作也不会被浪费。当您看到进展时,您将开始更好地看到项目风险。

你最初的 2to3 进度会很慢,但是工具和指导足够好,你会很快加快速度,所以在开始收集经验之前不要想太多。Django 方面取决于对框架中重大更改的了解,这就是为什么我认为最好尽早开始。

PS(有争议/个人意见)我没有太多使用六个或其他固定的 2 到 3 桥库。

这并不是因为我不信任它 - 它对于第 3 方库来说非常出色 - 而是因为我不想添加复杂的永久依赖项(而且我懒得阅读它的文档)。我已经用 3.x 兼容语法编写 2.7 代码很长时间了,所以我并不觉得有必要使用它们。 您的里程可能会有所不同,如果看起来工作量很大,请不要走这条路

相反,我创建了一个包含此类内容的py223.py(57 个 LOC,包括注释),其中大部分内容与标准库中弃用和名称更改的解决方法有关。

try:
    basestring_ = basestring
except (NameError,) as e:
    basestring_ = str

try:
    cmp_ = cmp
except (NameError,) as e:
    # from http://portingguide.readthedocs.io/en/latest/comparisons.html
    def cmp_(x, y):
        """
        Replacement for built-in function cmp that was removed in Python 3
        """
        return (x > y) - (x < y)

Run Code Online (Sandbox Code Playgroud)

然后从 py223 导入以解决这些特定问题。稍后我将放弃导入并将那些奇怪的内容移至isinstance(x, basestr_)isinstance(x, str)我事先知道没什么可担心的。