Py学习  »  Python

支持不同版本的python

Ram Rachum • 4 年前 • 1047 次点击  

这个问题困扰了我一段时间。

为了 my Python project 我希望能够支持python版本2.4到3.1。我考虑了一下如何做到这一点,最终决定为四个不同版本的python分别提供四个源代码分支:2.4、2.5、2.6和3.1。

我认为这是一个糟糕的决定,主要是因为python的发行版问题,现在我不得不做四次而不是一次。

问题是,怎么办?

我的项目是在科学计算领域。我的印象是,仍然有许多人依赖于Python2.4。

有人建议我只为2.4编写整个项目,但这对我来说是不可接受的。这将意味着我不能使用上下文管理器,这是我不会放弃的。

普通的python项目如何支持2.4?他们会避免使用上下文管理器吗?

另外,除了为python 3.1提供一个单独的fork之外,还有其他选择吗?我知道在2.x和3.x上运行相同的代码有各种各样的方法,但是我喜欢python的原因之一是因为代码很漂亮,我不能容忍用兼容性方法使它变得难看。

请给我你的意见。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/40239
 
1047 次点击  
文章 [ 6 ]  |  最新文章 4 年前
Marvin
Reply   •   1 楼
Marvin    12 年前

我们有相关的问题,一个支持Jython和CPython的大型系统返回到2.4。基本上,您需要将需要以不同方式编写的代码隔离到一组希望很小的模块中,并有条件地导入内容。

# module svn.py
import sys
if sys.platform.startswith('java'):
    from jythonsvn import *
else:
    from nativesvn import *

在您的示例中,您可能会对sys.version_info使用测试。您可以在实用程序模块中定义一些简单的东西,例如:from util import*

# module util.py
import sys
if sys.exc_info[0] == 2:
    if sys.exc_info[1] == 4:
        from util_py4 import *
    ...

然后util_py4.py中的内容如下:

def any(seq):                # define workaround functions where possible
    for a in seq:
        if a: return True
    return False
...

虽然这是一个不同于移植的问题(因为您希望继续支持),但是这个链接提供了一些有用的指导 http://python3porting.com/preparing.html (与其他关于移植Python2.x的文章一样)。

你说没有上下文管理器你就活不下去,这有点让人困惑。 虽然上下文管理器功能强大,使代码更具可读性,并将错误风险降至最低,但在2.4版本的代码中却无法使用它们。

### 2.5 (with appropriate future import) and later
with open('foo','rb')as myfile:
   # do something with myfile

### 2.4 and earlier   
myfile = None
try:
    myfile = open('foo','rb')
    # do something with myfile
finally:
    if myfile: myfile.close()

既然您想支持2.4,那么您将拥有一个只需使用第二种语法的代码体。两种写法真的会更优雅吗?

zeemonkee
Reply   •   2 楼
zeemonkee    14 年前

你可以试试 virtualenv 并使用单个python版本分发应用程序。不过,这在你的情况下可能可行,也可能不可行。

jathanism
Reply   •   3 楼
jathanism    14 年前

首先,您需要记住,Python2.x共享的语法基本上是相同的,这是向后兼容的,除了新增功能之外。还有其他一些不一定是错误的东西需要考虑,比如deprecationwarning消息,这些消息虽然不有害,但很难看,可能会导致混淆。

python 3.x在设计上是向后不兼容的,它打算把所有的旧东西都抛在脑后。Python2.6引入了Python3.x中的许多更改,以帮助简化转换。为了看到所有这些,我建议阅读 What's New in Python 2.6 文件。出于这个原因,很有可能为Python2.6编写也将在Python3.1中运行的代码,但这并非没有注意事项。

即使如此,即使在2.x版本之间也有许多细微的语法更改,这将要求您将大量代码包装在 try / except 如果这是你愿意做的,那么2.x和3.x分支是完全可能的。我想你会发现你会在你的对象上做很多属性和类型测试来做你想做的事情。

我建议您查看支持各种python版本的主要项目的代码。 Twisted Matrix 是第一个想到的。他们的代码是一个很好的例子,说明了应该如何编写python代码。

最后,你要做的事情并不容易,所以要为很多工作做好准备!

Peter Hansen
Reply   •   4 楼
Peter Hansen    14 年前

如果版本之间的差异不是极端的,您可以尝试将它们隔离到一个单独的包或模块中,在这个包或模块中您可以编写特定于版本的代码来充当适配层。

以一种简单的方式,在简单的情况下,这可以在不使用单独模块的情况下完成,例如当一个新版本的python使standard成为一个曾经是外部的包时,例如(例如)simplejson。我们在一些代码中有类似的东西:

try:
    import simplejson as json
except ImportError:
    import json

对于一些不重要的东西,比如你可能拥有的东西,你不会希望这些东西随机地散布在你的代码库中,所以你应该尽可能把它们收集在一个地方,并使之成为你的代码中唯一一个版本特定的部分。

对于语法不同的情况,比如您对希望使用上下文管理器的评论,这样做效果不太好。当然,您可以将上下文管理器代码放在一个单独的模块中,但这可能会使您使用它的地方复杂化。在这种情况下,您可以将某些关键特性(我认为上下文管理器可以很容易地模拟)移植到此适配器模块。

当然,拥有独立的代码库是你能做的最糟糕的事情,所以我当然建议你不要那样做。至少,不要随意使用较新版本的python中的特性,因为尽管将它们放在代码中看起来很不错(可能会简化特定的逻辑块),但必须通过分叉代码基(即使是在单个模块上)来复制该逻辑,这一事实将使韩寒否定了这些好处。

我们坚持使用旧版本的遗留代码,在新版本发布时进行调整以支持旧版本,但保持对旧版本的支持,有时使用小的适配器层。在某个时刻,我们的代码的一个主要版本出现在计划中,我们考虑是否是时候放弃对旧python的支持了。当这种情况发生时,我们试着跳过几个版本,直接从2.4升级到2.6,然后才真正开始利用新的语法和不适应性的特性。

Alan Franzoni
Reply   •   5 楼
Alan Franzoni    14 年前

你的问题似乎有不同的答案。

首先,如果你想提供 全部的 功能 全部的 python版本是的,您可能会被困在使用尽可能小的功能子集上,因此要为python 2.4编写代码。或者,如果新的解释器是纯python的话,可以从它们背后移植特性(上下文管理器和协同程序都不是这样)。

或者你可以将版本支持分成几个功能——如果你认为有一个(可选的)功能可以从上下文管理器中获得很大的好处,那么你可以在单独的模块中使用它,只需说2.4用户没有这个功能。

为了支持python 3,请看一下2to3助手,如果您正确地编写了代码,那么您很有可能不需要维护两个独立的代码基。

Mauve
Reply   •   6 楼
Mauve    14 年前

是的,您需要编写Python2.4语法来支持同一个代码库中的所有2.4-2.7。

Python2.6和2.7中的一些更改旨在使用3.x编写兼容代码更容易一些,但要做到这一点,您必须放弃对2.5及以下版本的支持。