簡體   English   中英

Python 2和Python 3雙重開發

[英]Python 2 and Python 3 dual development

我剛剛開始一個新的Python項目,理想情況下我想從一開始就提供Python 2和3支持,只需要很少的開發開銷。 我的問題是,為全新項目做這件事的最佳方法是什么?

作為安裝腳本的一部分,我遇到了運行2to3甚至3to2的項目。 這似乎是一種非常常見的方式。 但是,似乎有幾種不同的方法可以做到這一點。 我也遇到了Distribute

還可以選擇編寫多語言Python 2 / Python 3代碼。 即使這看起來像一個可怕的想法,我注意到我最近編寫的代碼更像是Python 3代碼,盡管我仍然以Python 2的形式運行它。我有一種感覺這只會幫助我自己的過渡時這一天終於到來了,並沒有為提供或至少幫助雙重支持做多少。

我提供的大多數提供雙重支持的項目都是后期添加了Python 3的支持,所以我特別好奇是否有更好的方法更適合新項目,你可以從中獲得清晰的好處。

謝謝!

您應該看看六個庫,它提供了一個統一的接口,可以處理Python 2和3之間不同的各種事物。

根據我的經驗,這取決於項目的類型。

如果它是一個庫或非常自包含的應用程序,則在Python 2.7中開發一個常見的選擇,盡可能避免在Python 3.x中棄用的構造,並采用自動化測試來識別py2to3留下的洞,您必須手動修復這些洞。

另一方面,對於現實生活中的應用程序,請准備不斷發現尚未移植到py3k的庫(有時是重要的庫)。 大多數情況下,您將別無選擇,只能將庫移植到Python 3,所以如果您能負擔得起,那就去吧。 通常我不能,這就是為什么我不支持Python 3用於這種項目(但是我很難編寫在適當的時候更容易移植的代碼)。

對於unicode處理,我發現這個PyCon 2012視頻非常有用。 這個建議適用於Python 2.x和3.x:將來自外部的每個字符串視為字節並盡快轉換為unicode,並盡可能晚地輸出字符串轉換為字節。 還有另一個關於日期/時間處理的非常豐富的視頻。

[更新]

這是一個古老的答案。 截至今天(2019年),使用Python 2.x啟動項目並沒有很好的理由,並且有幾個令人信服的理由將舊項目移植到Python 3.7+並放棄對Python 2.x的支持

根據我的經驗,最好不要使用像six這樣的圖書館 ; 相反,我只需要一個包含所需代碼的每個包的compat.py ,這與Scott Griffiths的方法不同 six也有嘗試支持長期以來的Python版本的負擔:事實上,當你接受Pythons <= 2.6和<= 3.2消失時,生活會更容易。 在2.7中有一些向后移植的兼容性功能,例如dict.view*方法,它們與Python 3上的非前綴版本完全相同; 另一方面,Python 3.3再次支持unicode字符串上的u前綴。

即使對於非常實質的軟件包, compat.py模塊(允許其他代碼保持不變)也可能非常簡短: 是我和我的同事幫助制作2/3多語言pika軟件包的一個例子 Pika是那些真正搞混合unicode和8位字符串的內部組件的項目之一,但現在我們已經在Python 3的生產中使用它超過6個月沒有問題。


其他重要的是在開發時始終使用以下__future__

from __future__ import absolute_import, division, print_function

我建議不要使用unicode_literals ,因為有些字符串需要在unicode_literals都是str類型。 如果您不使用 unicode_literals ,則可以執行以下操作:

  • b'123'是8位字符串文字
  • '123'在兩個平台上都是str類型
  • u'123'是兩個平台上正確的unicode文本

在任何情況下,請不要在安裝/包裝構建時 2to3; 過去曾經使用過一些軟件包 - 在Python 2上pip install這些軟件包需要花費幾秒鍾,但在Python 3上卻接近於分鍾。

選擇2或3,無論哪種是您喜歡的味道,並通過單元測試使其工作得非常好。 然后在通過py2to3或py3to2運行它之后確保這些測試有效。 最好維護一個版本的代碼。

我個人的經驗是,編寫在Python 2和3中都沒有改變的代碼更容易,而不是依賴於2to3 / 3to2腳本,而這些腳本通常無法完全正確地進行翻譯。

也許我的情況很不尋常,因為我正在做很多字節類型,2to3有一個很難的任務轉換它們,但是擁有一個代碼庫的便利性超過了代碼中有一些黑客的骯臟。

作為一個具體的例子,我的bitstring模塊是早期轉換為Python 3,相同的代碼用於Python 2.6 / 2.7 / 3.x. 源代碼超過4000行代碼,這就是我需要讓它適用於不同的主要版本:

# For Python 2.x/ 3.x coexistence
# Yes this is very very hacky.
try:
    xrange
    for i in range(256):
        BYTE_REVERSAL_DICT[i] = chr(int("{0:08b}".format(i)[::-1], 2))
except NameError:
    for i in range(256):
        BYTE_REVERSAL_DICT[i] = bytes([int("{0:08b}".format(i)[::-1], 2)])
    from io import IOBase as file
    xrange = range
    basestring = str

好吧,這不是很好,但這意味着我可以用優秀的Python 2樣式編寫99%的代碼,並且所有的單元測試仍然傳遞給Python 3中的相同代碼。這條路線不適合所有人,但它是一個選擇考慮。

如果您需要支持Python 2.5或更早版本,使用Distribute並且它的2to3集成通常是最好的方法。 但是如果你只需要支持Python 2.6或更高版本,我會在沒有轉換的情況下使代碼在Python 2和Python 3下運行。 我還會使用六個庫來使這更容易。

暫無
暫無

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

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