创建具有向后兼容性的软件包

时间:2019-10-27 09:38:34

标签: python

我尝试在 3.6 中创建python软件包,但我也想向后兼容 2.7 。如何为 3.6 编写代码和 2.7

例如,我有一个名为geo_point()的方法。

def geo_point(lat: float, lng: float):
    pass

此功能在 3.6 中工作正常,但在 2.7 中却不能,它显示语法错误,我认为 2.7 不支持类型提示。因此,我想编写 2.7 支持的另一个功能,并且当用户在 2.7 上运行我的程序包时,它将忽略所有不支持的功能

例如

 @python_version(2.7)
 def geo_point(lat, lng):
     pass

函数和python都可以决定哪个函数兼容吗?

4 个答案:

答案 0 :(得分:1)

如果类型提示是您的代码唯一的问题,请查看问题Type hinting in Python 2

它说,python3方面也要在注释行中键入提示。 Python2将忽略它,而python3则遵循这种替代语法。它是专门为仍必须与python2兼容的代码而设计的。

但是请注意,仅仅是因为代码是使用python2编译的,并不意味着它将产生正确的结果。

如果您还有更多的兼容性问题,我强烈建议您查看future模块(不要与from __future__ import xxx语句混淆。

您可以使用pip install future安装将来的(https://pypi.org/project/future/)。

由于您没有显示任何其他导致问题的代码,因此我无法就特定问题提供建议。

URL https://python-future.org/compatible_idioms.html显示了大量潜在的python 2 / python 3问题以及如何解决这些问题。

例如,在python 2中以较少的编码/ unicode问题打开文件,可以通过导入带有行的替代版本的open来完成

from io import open

https://python-future.org/compatible_idioms.html

附录

如果您确实需要为python3声明一个函数,为python2声明一个函数,则可以执行以下操作:

import sys

if sys.version_info < (3, 0):
    def myfunc(a, b):  # python 2 compatible function
        bla bla bla
else:
    def myfunc(a, b):  # python 3 compatible function
        bla bla bla

但是两个函数必须在语法上必须正确适用于python 2和python 3

如果您真的想拥有仅python2或仅语法上正确的python3函数(例如print语句或await),则可以执行以下操作:

import sys

if sys.version_info < (3, 0):
    from myfunc_py2 import myfunc  # the file myfunc_py2.py does not have to be python3 compatible
else:
    from myfunc_py3 import myfunc  # the file myfunc_py3.py does not have to be python2 compatible

答案 1 :(得分:0)

我怀疑是否值得这样做,但是作为概念证明:您可以结合使用装饰器和内置的exec()函数。使用exec()是避免语言差异引起的语法错误的一种方法。

这是我的意思:

import sys

sys_vers_major, sys_vers_minor, sys_vers_micro = sys.version_info[:3]
sys_vers = sys_vers_major + sys_vers_minor*.1 # + sys_vers_micro*.01
print('sys_vers: %s' % sys_vers)

def python_version(vers, code1, code2):
    lcls = {}  # Dictionary to temporarily store  version of function defined.

    if sys_vers == vers:
        exec(code1, globals(), lcls)
    else:
        exec(code2, globals(), lcls)

    def decorator(func):
        return lcls[func.__name__]

    return decorator


@python_version(2.7,
"""
def geo_point(lat, lng):
    print('code1 version')
""",
"""
def geo_point(lat: float, lng: float):
    print('code2 version')
""")
def geo_point(): pass  # Needed to know name of function that's being defined.

geo_point(121, 47)  # Show which version was defined.

答案 2 :(得分:0)

  

我认为2.7不支持类型提示

实际上,Python 2支持类型提示,并且您可以编写向后兼容的代码。参见the answer about Python 2 type hinting on StackOverflow

答案 3 :(得分:0)

虽然其他答案都强调类型提示,但我认为

六个软件包

可能会有帮助。项目基础和文档链接位于https://pypi.org/project/six/

  

Six是Python 2和3的兼容性库。它提供了一些实用程序函数,用于消除Python版本之间的差异,目的是编写在两个Python版本上都兼容的Python代码。有关提供的内容的更多信息,请参见文档。

Python 2和Python 3之间的显着区别之一是,打印语句中缺少括号会导致Python 3中的语法错误,例如

print "Hello, World"  # OK in Python 2, syntax error in Python 3.

六个解决了这些差异。