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


11

目前,我在一家大公司工作,我们需要将python2的旧的Django大项目转换为python3版本,因此我进行了大量研究,但仍然找不到最适合转换哪个版本的Python和Django的完美答案。

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

任何人都可以为上述python2到python3的旧版本推荐最适合我的Python和Django版本。


python3的当前版本是Python 3.8,而Django的最新版本是Django 3.0。Django的网站推荐python 3的最新版本是3.8。您是否有特定的原因为什么不想同时将python和django都加速到它们的最新版本?
Green Cloak Guy

2
有趣的是,几天前我才意识到,我已经维护了几年的基于Django的网站实际上是在使用python2.7托管的服务器上运行的,而我却一直在使用python3在本地运行。 7。我发现的唯一区别是,当我第一次尝试在某处使用f字符串,并且网络服务器的版本崩溃时;否则,出于测试和功能添加的目的,它一直在本地和远程完全按预期(完全相同)运行。我的全部轶事结论是Django通常与大多数东西兼容。
绿色披风家伙

1
对于最新版本,我发现有些人不建议这样做,因为在最新版本中,如果有与新更新有关的任何问题,那么有时将很难找到解决方案,因此在当前项目中,我不想冒此类风险,并且为了测试目的,我已经开始将我的项目转换为具有最新django的python 3.7.3最新版本,并且已经发现30种问题。
月亮

应该指出的是-这个问题是在我的审核审核中提出的。“是否有任何文档或参考”很明显是题外话(要求提供场外资源)。但是,我认为可以对问题进行编辑,以便更好地将其引向下面的公认答案。
–theMayer

Answers:


3

我以为我会在Wim的答案所倡导的策略中添加一些内容-首先在2.7和3.x上获得合适版本的Django-并概述一​​些对我有用的策略

Python 2.7是您的逃生舱,直到您在3.x上扳动扳机为止

  • 您的测试应该同时运行
  • 不要使用任何3.x特定功能,例如f字符串
  • 首先是Python 3.x,然后才是后来的在2.7上无法运行的Django 2.x
  • 尽早开始,不要过度分析,但要避免大爆炸
    • 首先逐个文件。
    • 从您具有测试套件的最低级别的代码(例如实用程序库)开始。
    • 如果可能的话,请尝试将所做的更改逐渐合并到2.7生产分支,并使3.x移植代码与产品更改保持最新。

开始使用哪个次要版本的Django?

我在这里的标准是Django迁移可以相当广泛地参与(实际上需要比2 => 3工作更多的思考)。因此,我将移动到最新和最好的1.11,以便您已经为2.7用户提供了一些价值。1.11上可能有大量的2.x之前版本的兼容垫片,并且您将收到其2.x弃用警告。

首先使用哪个次要版本的Python 3.x?

最好考虑所有方面,例如第三方库的可用性,CI / devops套件的支持以及所选服务器OS映像的可用性。例如,您始终可以安装3.8并尝试通过pip安装您的requirements.txt。

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

  • 单独的requirement.txt文件,但是...
  • 如果你有一个基于文件的,混帐回购协议,你可以在每个点VENV 同一代码行pip install -e <your directory>。这意味着,您可以在2个不同的终端中针对相同的单元测试运行2.7和3.x。
  • 您甚至可以在不同的端口上并排运行2.7和3.x Django服务器,并说Firefox和Chrome。
  • 经常提交(至少在porting分支上)并了解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而不是您的编辑器进行批量转换。

好处是,随着您对应用程序特定问题的了解越来越多,您可以构建一套可以在1个文件或多个文件上运行的更改,并完成大多数工作而不会破坏2.7或Django。在经过适当节流的2to3通行证应用此方法。这就使您在编辑器中残留了清理工作,并使测试通过。

(可选)在2.7代码上开始黑屏

black是一种代码格式化程序,它使用Python 3 AST进行分析。它不会尝试运行代码,但是会标记语法错误,以防止其进入AST阶段。但是,您将必须做一些点子安装全局魔术才能到达那里,并且您必须认可black的有用性。

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

#155转向Python 3的实际步骤应该为您提供一些工作思路。查看它的显示链接。他们喜欢谈论Instagram(?)的举动,该举动涉及在公共代码库和同一git分支上逐步将运行2.7代码转换为3.x语法,直到触发一天。

另请参见The Conservative Python 3移植指南

Instagram顺利过渡到Python 3-新堆栈

结论

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

  • DEV#1:使用2.7,从Django 1.11颠簸开始(理论上认为Django 1.11可能是到达Django 2.x的最佳起点)。

  • 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.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本身已经six用于兼容性层,因此,如果您想在过渡期间在Django项目中使用它,那么这并不是“添加复杂的永久依赖项”。
wim

@wim。我同意你的看法。六,但这取决于观点。我已经注意到,它带有第三方库,因此就需求和整体依赖性而言,它不会“花费”。但是我-也许是错误的-认为它在我的代码中间是一个大黑盒子/疣。如果您要做的只是测试实例字符串/ unicode / basestring之类的东西,并且如果您自己知道如何进行操作,那么您将确切地知道在不再需要垫片时如何退回垫片。不过,我将其移到最后。
JL Peyret

pip install -e ...(用小写字母-e),对吗?
thebjorn

可能是。将更正
JL Peyret

3

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

仔细阅读1.10.x和1.11.x的发行说明,检查是否已弃用并修复从1.9.x代码停止工作的所有内容。事情会破裂。Django发展迅速。对于大型Django项目,可能需要进行许多代码更改,并且如果您使用大量的第三方插件或库,则可能不得不考虑其版本。您的某些第三方依赖项可能已被完全放弃,因此您必须查找替换项或删除功能。

要查找每个版本升级的发行说明,只需谷歌“ Django的新功能”。这些匹配将精心记录所有弃用和更改:

一旦webapp在Django 1.11上运行正常,并且所有测试都通过了( 确实有一个测试套件,对吗?),则可以进行Python 3转换,同时保持Django版本不变。Django 1.11最多支持Python 3.7,因此这将是一个不错的目标版本。到处都是unicode,因为字节和文本之间的隐式转换现在已经不复存在,并且许多Python 2 webapp都依赖于此。

一旦该项目在Django 1.11和Python 3.7上运行良好,然后您就可以考虑升级到Django 3.0,遵循与之前相同的过程-阅读发行说明,进行必要的更改,运行测试套件并签出开发服务器中的webapp手动。


1
肯定要走的路。获取测试代码以在2.7和3.x上运行。您可以使用指向2个不同的virtualenvs指向相同的git repo pip install -E。单元测试运行后,开始使用Django-on-3x进行测试,并再次使代码在2和3中正常工作。在进行一些仔细的编码后,请注意不要烧掉2.7网桥-例如,没有f字符串-切换将是非常滑稽。一旦3.x完全稳定,请开始使用仅3.x代码。优点是生产2.7始终处于切换状态,直到切换为止。
JL Peyret

2

我会先升级到py3。您需要setup.py在stable / 1.9.x分支(https://github.com/django/django/blob/stable/1.9.x/setup.py)上的Django存储库中查看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不太关心向后兼容性,因此,我通常建议在升级路径上点击每个次要版本(或至少确保您阅读了“向后”不兼容”和每个次要版本的弃用列表)。

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


1
测试覆盖率+1。这是关键指标,无论最终采用哪种方法。当试验普遍的代码更改时,这确实有帮助,我是说这完全不是 TDD红色/绿色测试的狂热者。找出确定2.7结果基线的方法,升级变得容易得多。
JL Peyret

2

我的项目遇到同样的问题,并且我在Django 2.2.7版中尝试了python 3.7.5。

您不应该使用python最新版本3.8或Django最新版本3.0,因为您可能会因某种错误而无法获得最新版本的正确解决方案。


这应该是一条评论
Bruno

-2

您应该尝试拍摄当前版本。Python 3.8和Django3.0。Six库将有助于一些常规更改。无论哪种方式,您都必须进行一些重构,以便您最好使其成为最新的。


3
您是否曾经进行过Django升级?这只是一厢情愿。从2.7 / 1.9直接进入Python 3.8和Django 3.0几乎是不可能的。即使将较小的版本(如Django 1.9)升级到1.10也可能是一个困难的过程,需要进行许多代码更改。
wim

是的,我已经获得了奢侈和时间上的批准,可以进行完整的重构并使应用程序保持最新。同样,对于大多数人来说,应用程序大小,逻辑和时间限制都是一个很大的问题,但他们从未提到过应用程序大小或时间限制,因此我推荐了“最佳解决方案”或“如意算盘”的观点;)
Dave

此外,如果您还需要担心Ansible以及在LTS Ubuntu上运行的问题,您会发现Ubuntu 18.04甚至缺少3.7支持。我听过的安全播客建议让3.8稳定一点直到发布点或2. -1为止,以避免不必要的风险。
JL Peyret

有什么好的安全播客建议吗?
戴夫

对于Python sec,请收听listennotes.com/podcasts/talk-python-to-me / ... 但是,我认为当心3.8的同时发生是最近的。 冒险生意是一种很好的娱乐性安全播客,尤其是如果您遵循国际关系的话。不好意思道歉,但是,是的,在您的情况下起作用的东西可能会在其他情况下使其他人感到沮丧。为2〜3变换看到 listennotes.com/podcasts/talk-python-to-me/...
JL Peyret
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.