簡體   English   中英

將非多語言代碼從 Py2 移植到 Py3 的巧妙方法

[英]Neat way to port nonpolyglot code from Py2 to Py3

在我的許多 python 模塊中,我正在使用

from itertools import izip_longest

但現在我正在將我的代碼庫移動到 Py3(同時與 Py2 兼容)。 而在 Py3 中,izip_longest 被重命名為 zip_longest。 Failing to import itertools in Python 3.5.2中建議解決此問題的一個答案,即將導入語句更改為以下。

try:
    # Python 3
    from itertools import zip_longest as izip_longest
except ImportError:
    # Python 2
    from itertools import izip_longest 

但是,在 20 多個模塊中更改它對我來說有點奇怪。 這樣做的巧妙方法是什么?

您可以將確切的代碼包裝在您自己的模塊中,例如itertools_compat.py ,然后編寫

from itertools_compat import izip_longest

無論您在哪里需要這個 function。

使 python2 代碼與 python3 一起工作不是免費的。 並且涉及很多繁重的工作。 我認為很難避免這種情況,無論如何您都必須進行適當的測試以確保您的代碼在兩個版本中都可以使用。

我不知道你的代碼和你的項目,它的確切內容,這個項目是否應該存活更長時間,或者你只是想讓它存活更長時間。 因此,我不確定在您的情況下什么是最好的。

一般來說,我建議更改您的代碼,使其看起來像 python3 代碼並且仍然使用 python2 運行,而不是編寫看起來像 python2 代碼但也可以使用 python3 運行的代碼。 (但一切都取決於你的上下文)

您可能想嘗試 package future https://python-future.org/它為編寫代碼提供了幫助程序,這兩個版本都運行。

future還包含一些工具,這些工具會嘗試以某種方式自動更改代碼,從而更有可能在兩個版本中運行。 根據代碼的復雜性,您仍然需要手動執行一些操作(尤其是對於 unicode 問題)

這些命令稱為futurize (使代碼看起來像 python3,但使用 python2 運行)或pasteurize (使代碼看起來像 python2,但也使用 python3 運行)

在嘗試之前備份所有文件(或使用 git 之類的版本控制)。

簡單的用例是futurize --stage1 yourfile.py

有一個有趣的章節/ 備忘單有很多例子,值得一讀

如果您不想使用未來的 package 或者如果您遇到情況,那么未來不能很好地處理我會編寫一個適配器模塊並在您的代碼中使用它。

例如py2py3compat.py:

try: 
    # Python 3 
    from itertools import zip_longest
except ImportError: 
    # Python 2 
    from itertools import izip_longest as zip_longest

你的pyfile.py:

from py2py3compat import zip_longest

並執行全局搜索和替換以將izip_longest替換為zip_longest

我看到你的另一個問題已經結束,所以我會在這里發帖。 所以,有幾個文件,命名很重要!

fixer.py

#!/usr/bin/env python3
# you'll need 2to3 and python-modernize installed
from __future__ import absolute_import
import sys
from lib2to3.main import main
import libmodernize

sys.path.append(".")
sys.exit(main('fixers'))

fixers/fix_iziplongest.py

from lib2to3 import fixer_base
import libmodernize

class FixIziplongest(fixer_base.BaseFix):
    PATTERN = """
    power< 'izip_longest' trailer< '(' any* ')' > >
    | import_from< 'from' 'itertools' 'import' 'izip_longest' >
    """

    # This function is only called on matches to our pattern, which should
    # be usage of izip_longest, and the itertools import
    def transform(self, node, results):
        # add the new import (doesn't matter if we do this multiple times
        libmodernize.touch_import('itertools_compat', 'zip_longest', node)
        # remove the old import
        if node.type == syms.import_from:
            node.parent.remove()
            return node
        
        # rename to izip_longest
        node.children[0].value = 'zip_longest'
        return node

用法與2to3 - python./fixer.py -f iziplongest file_to_fix.py相同(如果您希望它應用更改,則需要更多標志,這只會顯示差異)所以,它的作用是隱藏這個:

from itertools import izip_longest
for x in izip_longest(a, b):
     print(x)

對此:

from itertools_compat import zip_longest
for x in zip_longest(a, b):
     print(x)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM