适应(Python)语言更改的策略


16

编写仍将运行数年的代码

编程语言会改变。图书馆变化。5、10甚至20年以前的某些代码可能仍会运行并产生预期的结果,而2年之后的某些代码可能会因语法错误而失败。这是部分不可避免的,因为语言会不断发展(至少大多数会这样做)。开发人员有责任维护其代码。但是有时候,稳定性是生产代码中的一个重要要求,并且代码应该只运行10年,而无需每年有人通过代码来适应语言变化。或者,我可能有一些小脚本,例如用于科学数据分析的脚本,在多年不接触它们之后我需要重新访问。例如,在气象部门,即使对于非速度必不可少的部分,也有许多可操作的Fortran代码,而代码稳定性是原因之一。一世' 我们听说过对不稳定的恐惧是他们反对迁移到Python的目的之一(当然,除了语言惯性之外,这还可能是新代码不依赖于旧代码)。当然,稳定代码的一种策略是冻结整个操作系统。但这并不总是可行的。

我以Python为例,但问题不仅限于Python。

有关Python兼容性问题的文档

对于Python,有几个文档概述了向后不兼容更改的策略。

PEP-5

根据PEP 5

从Python过渡版本的发行到向后不兼容版本的发行,必须至少有一年的过渡期。用户将有至少一年的时间来测试他们的程序,并将其从使用已过时的结构迁移到替代结构。

我个人认为一年是很短的。这意味着我可能会编写一些代码,并且从现在起1.5年前它将不再运行。

PEP 291

PEP 291包含不完整的准则指南清单,应避免使用这些准则以保持向后兼容性。但是,它仅与Python 2.x有关。由于Python 2.7是2.x系列的最终版本,而Python 2.7仅是错误修复,因此该PEP现在仅具有历史意义。

PEP 387

向后不兼容的更改也有PEP 387。PEP 387是草案,不是官方政策。2009年6月,在Python-ideas邮件列表中对此进行了讨论。讨论的一部分重点在于开发人员如何编写可抵御语言更改的强大代码。一篇文章列出了一些关于该做什么的建议

随之而来的是,您可以推断出在大多数情况下可能是正确的几条规则:不要调用以开头的东西"_",不要猴子打补丁,不要对除您自己以外的类中的对象使用动态类替换,不要依赖于继承层次结构的深度(例如no ".__bases__[0].__bases__[0]"),请确保您的测试在运行时不会产生任何DeprecationWarnings,将属性添加到从其他库继承的类时,请注意潜在的命名空间冲突。我不认为所有这些东西都写在一个地方。

此外,还有一些关于“矿场”(可能会更改的新功能)和“冻结区域”(实际上已保证几乎售出的API不变)的观点。引用安托万·皮特鲁Antoine Pitrou)

我认为应该对“冻结区域”进行积极的定义(明确的公共API和明确保证的行为),而不是进行消极的定义(明确的“雷区”)。否则,我们将忘记将一些重要的东西放进雷区,并在以后需要以向后不兼容的方式更改这些东西时被咬住。

这个线程似乎没有任何结论,但是它非常接近我要寻找的核心。该线程已使用了将近四年,因此情况可能已更改或改善。什么样的代码可能会生存,而哪种代码更脆弱?

移植指南

除了上面概述的文档之外,每个Python版本还附带一个移植指南:移植到Python 3.2移植到Python 3.3等。

有用的兼容性

PEP 3151向我介绍了有用的兼容性的概念。用我自己的话来说,可以归结为这样一个想法,即只有精心编写代码,语言开发人员才需要小心维护兼容性。它并没有真正定义有用的兼容性,但是我认为它与我在上面的PEP 387讨论中引用的想法相似。

从程序员的角度

作为一名程序员,我知道Python将来会发生变化,人们(尤其是我自己)将在几年后尝试使用一个,两个或三个次要版本的Python版本运行我的代码。并非所有的东西都兼容,实际上,很容易提出会失败的代码(我曾经遇到过说明的代码if sys.version[:3] != '2.3': print 'Wrong version, exiting')。我正在寻找一组有关如何执行和 执行哪些操作的准则,以增加我的代码将来仍可不变运行的机会。

有没有这样的指导方针?如何编写将来仍会运行的Python代码?

我的问题既涉及Python的核心,其标准库,也常用附加库,特别是numpyscipymatplotlib


编辑:到目前为止,两个答案与python2和python3有关。这不是我的意思。我知道从Python2迁移到Python3的工具。我的问题是关于语言的变化尚未到来。在寻找更稳定的编码准则方面,我们可以做得比水晶球更好。例如:

  • import module比更具前瞻性from module import *,因为如果module增加一个或多个新函数/类,后者可能会破坏代码。

  • 与未使用文档的方法相比,使用未记录的方法可能无法保证未来的发展,因为未记录的内容可能表示某些内容尚不稳定。

我追求的是这种实用的编码建议。由于它是关于当下→未来的内容,因此我们可以将自己限制为Python3,因为Python2不会再改变了。

Answers:


13

这是我们领域中尚未解决的问题。无法确定您的代码将无限期地工作。即使您的代码在向前兼容的意义上确实是完美的(如果确实如此,请为我公司工作!;)),如果该代码可以运行,使用或被任何其他存在错误或变更的软件使用,无论如何,您的代码可能无法正常工作。

因此,我无法给您提供执行此操作的清单,如果您遵循这些清单,则可以保证成功。但是,您可以做的是最大程度地减少将来发生损坏的风险,并将其影响降到最低。一个知识渊博的Python专家将能够为您提供更特定于Python的建议,因此我将必须更笼统:

  • 编写单元测试。即使对于您知道不需要的东西。

  • 使用流行的/设计良好的/稳定的库和技术,避免使用不受欢迎的(因此可能很快将不再受到支持)

  • 避免编写利用实现细节的代码。编码到接口,而不是实现。针对同一接口的多个实现进行编码。例如,在CPython,Jython和IronPython中运行代码,然后看看会发生什么。这会给您一些有关您的代码的反馈。不过,这可能对Python3没有帮助-上一次我听说,某些实现仍在Python2中。

  • 编写简单明了的代码,明确假设

  • 编写模块化的可组合代码。如果某些代码必须做一些危险的事情(从面向未来的角度来看),请将其分开,以便即使必须更改,其余的代码也不需要。

  • 有某种形式的规范。如果将测试用作规范,则这与关于单元测试的要点相似,也可以将其用作规范,这与接口有关。 (我的意思是一般意义上的接口,而不是Java关键字意义上的接口)。

做任何这些事情可能会/将增加您要做的工作量。我认为这是有道理的-在我看来,如何编写好的代码也有很多要点。有时您可能需要违反其中一些建议。这是完全可以接受的,但请注意成本。

Python团队正在考虑这一点真是太好了,并且可以肯定的是,他们比我以前有更多的才华和技能。不过,我估计仍有100%的人的某个地方的代码将无法按照升级Python时的预期方式工作。


4

称为配置管理。 如果系统从未更改,则它不会中断。因此,请勿更改系统。担心新的Python版本?不要升级。担心新的设备驱动程序?不要升级。担心Windows补丁?...


0

对于Python 2-> Python 3,已经安装了Python 2to3库(原始Python软件包随附)。

基于此,在发布新版本后不久,每个新版本都应该包含类似的库。但是,正如Martijn所言,此类库仅针对主要版本(如3.0版)发布,而不会针对次要版本(如3.2版)发布。但是,在3.0和3.2(或任何其他次要版本)之间,应该不存在任何兼容性问题,因此转换为3.0版应该没问题。

另外,我建议您看看这个问题


1
不可以,2to3仅可帮助您跨主要版本差距升级代码。无需库即可在次要版本之间升级代码。
马丁·皮特斯

@MartijnPieters次要版本不应有兼容性问题,因为不应有太大的更改。如果存在兼容性问题和较大的更改,应发布一个全新的版本。

0

我没有太多要添加的内容,“ 2程序,并使用2to3”似乎是最近在互联网上常见的添加内容。但是,您应该注意以下几点:

称为六个(pypi页面)。它是一个致力于帮助编写可同时在python 2和python 3上运行的代码的python库。


并不是我真正想要的。我已经编辑了问题,希望可以更清楚地了解我现在要寻找的内容。
gerrit
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.