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

For Python2 to Python3 code conversion, Which version of Python & Django best suited?

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

目前我使用的是 Python : 2.7.16 & Django : 1.9.13 我的旧版本。

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

您应该尝试为当前版本拍摄。 Python 3.8 和 Django 3.0.The 六个库将有助于进行一些约定更改。无论哪种方式,您都将不得不进行一些重构,因此您不妨将其更新为最新版本。

我的建议是先升级到 Django==1.11.26,这是支持 Python 2 和 Python 3 的最新版本的 Django。保持当前版本Python 目前为 2.7。

仔细阅读 1.10.x 和 1.11.x 的发行说明,检查弃用情况并修复 1.9.x 代码中停止工作的所有内容。事情会破裂。姜戈动作很快。对于大型 Django 项目,可能需要进行许多代码更改,如果您使用大量第 3 方插件或库,则可能需要调整它们的版本。您的某些第 3 方依赖项可能已被完全放弃,因此您必须找到替代品或删除这些功能。

要查找每个版本升级的发行说明,只需 google "What's new in Django "。命中将详细记录所有弃用和更改:

一旦 webapp 在 Django 1.11 上运行良好,所有测试都通过(你 有一个测试套件,对吧?)然后你可以做 Python 3 转换,同时保持 Django 版本不变。 Django 1.11 最高支持 Python 3.7,因此这是一个很好的目标版本。到处都是 unicode,因为字节和文本之间的隐式转换现在已经消失,许多 Python 2 webapps 都依赖它。

一旦项目似乎在 Django 1.11 和 Python 3.7 上运行良好,那么您可以考虑升级到 Django 3.0,按照与以前相同的过程 - 阅读发行说明,进行必要的更改,运行 测试套件,并在开发服务器中手动检出 webapp。

我想我会在 Wim 的回答所提倡的 策略 中添加一点——首先获得适用于 2.7 和 3.x 的 Django 版本——并且概述一些对我有用的策略

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 套件的支持以及所选服务器 OS 图像的可用性。例如,您始终可以安装 3.8 并尝试通过 pip 安装 requirements.txt。

利用git(或者你使用的任何scm)和virtualenv.

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

利用2to3

是的,如果你愿意,它会破坏 2.7 代码和 Django。所以...

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

  • 将其限制为仅不会破坏 2.7 或 Django 的某些转换。 print x=> print (x)except(Exception) as e 是 2 个简单的选择。

这是我的节流命令的样子:

2to3 $tgt -w -f except -f raise -f next -f funcattrs -f print
  • 运行 逐个文件,直到您真正有信心为止。

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

优点是,随着您越来越了解应用的具体问题,您可以构建一套更改,可以 运行 对一个文件或多个文件进行更改,并完成大部分工作不破坏 2.7 或 Django。在 适当节流的 2to3 通过后应用此 。这让您在编辑器中进行残留清理并让您的测试通过。

(可选)在 2.7 代码上开始 运行ning black

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

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

聆听 #155 Practical steps for moving to Python 3 应该会让您对作品有所了解。查看它的显示链接。他们喜欢谈论 Instagram(?) 的举动,其中涉及在公共代码库和相同的 git 分支上将 运行ning 2.7 代码逐渐调整为 3.x 语法,直到 pull -触发日。

另见 The Conservative Python 3 Porting Guide

Instagram Makes a Smooth Move to Python 3 - 新堆栈

结论

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

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

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

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

你最初的 2to3 进步会很慢,但工具和指导足够好,你会很快加快速度,所以在开始积累经验之前不要想太多。 Django 方面取决于 接触框架中的重大变化,这就是为什么我认为最好早点开始。

P.S。 (controversial/personal 意见)我没有使用 six 或其他固定的 2 对 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)

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

我会先升级到py3。您需要查看 stable/1.9.x 分支 (https://github.com/django/django/blob/stable/1.9.x/setup.py) 上的 Django 存储库中的 setup.py 以了解支持的 py3 版本是 3.4(死)和 3.5.

一旦你使用了 py3.5 和 Django 1.9,你可以一次升级一个,直到你达到你想要结束的版本。例如。 Django 1.11 支持 py3.5 和 py3.7,所以

py27/dj19 -> py35/dj19 -> py35/dj1.11 -> py37/dj1.11 ... -> py37/dj2.2

dj2.2 是第一个支持 py3.8 的版本,但如果您在通常保守的环境中工作,我可能会停在 py37/dj2.2。

如果您有其他软件包,则需要找到可在每个步骤中协同工作的版本组合。制定计划是关键,一次只升级一个组件通常最终会节省您的时间。

未来的库 (https://python-future.org/) 将帮助您解决许多棘手的情况,而您需要在 py27 和 3.x 上编写 运行 代码。六也很棒。我会避免推出自己的兼容层(为什么要重新发明轮子?)

如果可能的话,在开始之前尽量让你的单元测试覆盖率达到 75-85%,并且一定要为每个升级步骤在 "from" 和 "to" 版本上设置自动测试.在升级到下一个版本之前,确保你阅读并修复了 Django 的所有警告——Django 很少关心向后兼容性,所以我通常建议在升级路径上点击每个次要版本(或者至少确保你阅读 "backwards incompatibilities" 和每个次要版本的弃用列表)。

祝你好运(我们现在正在从 py27/dj1.7 升级 300+Kloc 代码库,所以我感受到你的痛苦 ;-)

我的项目也有同样的问题,我已经尝试 python 3.7.5 和 Django 版本 2.2.7。

您不应该使用 python 最新版本 3.8 或 Django 最新版本 3.0,因为对于任何类型的错误,您可能无法获得最新版本的正确解决方案。