Python - 如何在旧版解释器上运行为新版本编写的代码?

0 投票
1 回答
728 浏览
提问于 2025-04-18 07:23

编辑: 最后我成功了,但整个过程真是太麻烦了,以后开发的时候我一定会听从@Martijn Pieters的建议。

我刚学Python,需要把我在Windows(cygwin)上做的一个Python项目转移到Linux上。这个项目用到了ipaddress模块。我在Linux机器上没有管理员权限,也没有网络连接,所以无法安装任何东西。因此,我把我的项目文件(ipfind_v5.py)和在cygwin的/lib/python2.7/site-packages目录下找到的ipaddress.py模块都复制到了Linux的一个文件夹里。问题是,当我运行这个脚本时,出现了以下错误:

[wakatana@zeus]$ python ipfind_v5.py
Traceback (most recent call last):
  File "ipfind_v5.py", line 28, in ?
    import ipaddress as IP
  File "/home/wakatana/ipfind.py/ipaddress.py", line 28
    if b'\0'[0] == 0:  # Python 3 semantics
           ^
SyntaxError: invalid syntax

我把

if b'\0'[0] == 0:

替换成了

if '\x00' == 0:

但又出现了另一个错误:

[wakatana@zeus ipfind.py]$ python ipfind_v5.py
Traceback (most recent call last):
  File "ipfind_v5.py", line 28, in ?
    import ipaddress as IP
  File "/home/wakatana/ipfind.py/ipaddress.py", line 1123
    except ValueError as exc:
                       ^
SyntaxError: invalid syntax

然后根据这篇关于异常的文章https://docs.python.org/2/tutorial/errors.html,我做了:

sed -i 's/ as exc/, exc/' ipaddress.py

之后我又遇到了另一个错误(ipaddress模块的源代码在这里:https://github.com/phihag/ipaddress/blob/master/ipaddress.py):

[wakatana@zeus ipfind.py]$ python ipfind_v5.py
Traceback (most recent call last):
  File "ipfind_v5.py", line 28, in ?
    import ipaddress as IP
  File "/home/wakatana/ipfind.py/ipaddress.py", line 1173
    if isinstance(b, bytes)
     ^
SyntaxError: invalid syntax

然后我重写了这一部分:

return u'.'.join(_compat_str(struct.unpack('!B', b)[0]
                             if isinstance(b, bytes)
                             else b)
                 for b in _compat_to_bytes(ip_int, 4, 'big'))

变成了这个(希望这是等价的,似乎代码运行得不错):

retval=[]
for b in _compat_to_bytes(ip_int, 4, 'big'):
  if isinstance(b, str):
    retval.append(_compat_str(struct.unpack('!B', b)[0]))
  else:
    retval.append(b);

return unicode(".".join(retval))

还需要另外两个步骤: 把bytes改成str 把:from . import foo改成:import foo

配置:

Linux版本: Python 2.4.3

Windows(cygwin)版本: Python 2.7.3

1 个回答

2

你不能让Python 2.4运行Python 2.7的代码,这个是不行的。

Python项目遵循一种叫做语义版本模型的规则,使用MAJOR.MINOR.PATCH的编号方式。Python保证在补丁版本之间,语法是不会改变的;也就是说,2.4的代码在2.4.x的版本中是可以正常工作的,前提是没有bug。在小版本之间,Python会尽量保持向后兼容;也就是说,早期的2.x版本写的代码在后来的版本中尽可能也能正常运行。因此,写给2.4的代码在Python 2.7中仍然可以运行。Python 3是一个新的大版本,里面引入了很多不兼容的重大变化。

比如,从except Exception, name:改成except Exception as name:就是一个这样的变化,这个改动是在Python 2.6中引入的;旧的语法容易出错,而新的语法让你更清楚地知道你是在把捕获的异常绑定到一个名字上。

不过,Python也做了一些努力,让你可以更容易地写出同时能在Python 2.x和Python 3.x上运行的代码。这包括在Python 2.x的版本中添加一些语法,使得这些语法在Python 3中才能正常工作。

例如,b'...'这种语法就是一个变化。在Python 3中,Python 2的str类型被bytes类型取代,而b'..'表示字节字符串的语法。因为bytes实际上就是Python 2中的旧str类型,所以你可以从Python 2.6开始使用b'...',这会得到一个普通的Python 2字符串对象。相反,更新的Python 3.x版本接受u'...'作为字符串字面量的语法,而在Python 2中,这会得到一个Unicode字符串。

每个大版本和小版本的更新都会在新特性部分中记录下变化和新增内容,如果你想把代码移植到Python 2.4,就得仔细阅读这些文档。

没有什么“通用转换器”可以做到这一点。确实有工具可以在Python 2和Python 3的语法之间转换(比如2to33to2工具),但这些工具无法帮助你把2.7兼容的代码移植到2.4。

不过,编译一个Python解释器并安装到你的家目录是相对简单的,不需要root权限。我会下载Python 2.7,用./configure --prefix=$HOME配置,然后运行makemake install,这样就可以把它安装到~/bin/~/lib/python2.7/中,然后用这个二进制文件运行脚本。

撰写回答