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



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

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

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

我想我应该为Wim的答案所倡导的策略添加一点-首先获得适用于2.7和3.x的Django版本-并概述一些对我有效的战术。

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

  • 您的测试应该在两个
  • 不要使用任何3.x特定的功能,比如f-string
  • 首先是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的哪个次要版本开始

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

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

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

使用2to3

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

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

  • 将其限制为只有不会突破2.7或Django的某些转换。CCD_ 3=>CCD_ 4和CCD_。

这就是我的节流命令:

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

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

优点是,当你越来越了解应用程序的具体问题时,你可以构建一套可以在一个文件或多个文件上运行的更改,并在不破坏2.7或Django的情况下完成大部分工作。在适当调节的2to3通过后应用此。这会在编辑器中留下剩余清理,并使测试通过。

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

black是一个代码格式化程序,它使用Python3AST来运行它的分析。它不会尝试运行代码,但会标记阻止它进入AST阶段的语法错误。你必须使用一些pip安装全局魔法才能达到目的,你必须相信black的有用性。

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

听#155转到Python3的实际步骤应该会给你一些工作的想法。看看它的节目链接。他们喜欢谈论Instagram(?)的举动,这涉及到在一个公共代码库和同一个git分支上逐渐调整运行2.7代码到3.x语法,直到触发日。

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

和Instagram顺利移动到Python 3-新的堆栈

结论

你到Django 1.11 EOL(2020年4月)的时间很短,所以如果你有2个以上的开发资源,我会考虑同时做以下事情:

  • DEV#1:从Django 1.11凸起开始(理论上Django 11.1可能是Django 2.x的跳起点),使用2.7。

  • DEV#2:开始使用Python 3.6/3.7的非Django实用程序代码。由于代码在这一点上是2.7兼容的,所以在进行时将其合并到#1中。

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

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

附言(有争议/个人观点)我不太使用six或其他罐装的2到3桥接库

它不是,因为我不信任它——它对第三方libs来说非常棒——而是因为我不想添加一个复杂的永久依赖项(而且我懒得阅读它的文档)。很长一段时间以来,我一直在用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),但我事先知道没有什么可担心的。

我的建议是首先升级到Django==1.11.26,这是Django的最新版本,同时支持Python 2和Python 3。现在请继续使用您当前版本的Python 2.7。

仔细阅读1.10.x和1.11.x的发行说明,检查是否有弃用,并修复1.9.x代码中停止工作的任何内容。事情会破裂的。Django动作很快。对于一个大型的Django项目,可能需要进行许多代码更改,如果你使用了大量的第三方插件或库,你可能不得不改变它们的版本。你的一些第三方依赖可能已经被完全放弃,所以你必须找到替代品或删除这些功能。

要查找每个版本升级的发布说明,只需在谷歌上搜索"Django的新增功能"。点击将仔细记录所有的弃用和更改:

  • https://docs.djangoproject.com/en/2.2/releases/1.10/
  • https://docs.djangoproject.com/en/2.2/releases/1.11/

一旦Web应用程序在Django 1.11上运行良好,所有测试都通过了(你有一个测试套件,对吧?),那么你就可以进行Python 3转换,同时保持Django版本不变。Django 1.11最高支持Python 3.7,因此这将是一个很好的目标版本。到处都是unicode,因为字节和文本之间的隐式转换现在已经不复存在,许多Python 2 Web应用程序都依赖于此。

一旦项目在Django 1.11和Python 3.7上运行良好,那么您可以考虑升级到Django 3.0,遵循与以前相同的过程——阅读发行说明,进行必要的更改,运行测试套件,并手动在开发服务器中检查Web应用程序。

我会先升级到py3。您需要查看stable/1.9.x分支上Django repo中的setup.py(https://github.com/django/django/blob/stable/1.9.x/setup.py)计算出支持的py3版本是3.4(dead)和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上运行代码时,它将帮助您处理许多棘手的情况。6也很棒。我会避免滚动你自己的兼容层(为什么要重新发明轮子?)

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

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

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

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

您应该尝试为当前版本拍摄。Python 3.8和Django 3.0.Six库将帮助进行一些约定更改。无论哪种方式,你都必须进行一些重构,这样你就可以让它成为最新的。

最新更新