我想看看是否有任何需要最小化Python版本的方法。如何編寫能夠正確需要最小python版本的Python代碼?
由於新的異常處理(as
關鍵字),我有幾個需要Python 2.6的Python模塊。
它看起來,即使我在我的腳本的開頭檢查python版本,代碼將無法運行,因爲解釋器將在模塊內部失敗,拋出一個醜陋的系統錯誤,而不是告訴用戶使用新的python 。
我想看看是否有任何需要最小化Python版本的方法。如何編寫能夠正確需要最小python版本的Python代碼?
由於新的異常處理(as
關鍵字),我有幾個需要Python 2.6的Python模塊。
它看起來,即使我在我的腳本的開頭檢查python版本,代碼將無法運行,因爲解釋器將在模塊內部失敗,拋出一個醜陋的系統錯誤,而不是告訴用戶使用新的python 。
import sys
if sys.hexversion < 0x02060000:
sys.exit("Python 2.6 or newer is required to run this program.")
import module_requiring_26
而且這個涼爽的部分是,它可以包含在__init__
文件或模塊內。
您不希望在Python 3下運行腳本嗎? – 2011-06-03 09:04:11
這是Walter Mundt的回答的劣質版本,在這之前已經發布。 – 2017-05-27 08:22:51
我猜你有這樣的:
import module_foo
...
import sys
# check sys.version
但module_foo需要一個特定的版本呢?既然如此,這是完全合法的。因此重新安排你的代碼:
import sys
# check sys.version
import module_foo
Python並不需要進口,除了from __future__ import [something]
在你的代碼的頂部。
您不應該在腳本本身內部使用任何Python 2.6功能。此外,在導入任何需要新Python版本的模塊之前,您必須先進行版本檢查。
E.g.啓動腳本,像這樣:
#!/usr/bin/env python
import sys
if sys.version_info[0] != 2 or sys.version_info[1] < 6:
print("This script requires Python version 2.6")
sys.exit(1)
# rest of script, including real initial imports, here
+1。我在你的'print'中添加了一些括號,因爲否則就像Tim指出它會在Python 3中出現一個'SyntaxError'失敗(這是棘手的事情!)我認爲這是最正確的方法 - 我的方法更快,但是一點點黑客。 – 2011-06-03 10:37:19
我不認爲它有必要在Python 3中工作。畢竟,Python 3通常不是與Python 2.x兼容的源代碼。由於需要分發幾乎任何東西的單獨Python 2.x和3.x版本,因此您可以完全退出Python 3.x版本。 – 2011-06-06 14:31:35
即使嘗試使用_3.x_運行腳本,也可以優雅地退出,但除非_entire_腳本碰巧是be_syntactically_ valid 3.x,否則這將不起作用。 'print'不是打印錯誤消息的好選擇,因爲它默認打印到_stdout_;簡單的解決方案是使用'sys.exit(「這個腳本需要Python 2.x,> = 2.6」')(如在公認的答案中),它打印到_stderr_並且也用代碼1退出。在Windows上,當使用'pythonw.exe'調用時,您必須對錯誤進行額外處理才能顯示出來。) – mklement0 2015-08-15 21:44:04
(見本question也)我發現要做到這一點最簡單的方法就是加入這樣一行:在文件開始
b'You need Python 2.6 or later.'
。這利用了字節文字是在2.6中引入的事實,因此任何早期版本都會使用您提供的任何消息作爲堆棧跟蹤來提升SyntaxError
。
如果您需要Python 2.7版,怎麼樣:
{'You need Python 2.7 or later.'}
這是在2.6語法錯誤。
對於Python 2.5這應該工作:
'You need Python 2.5' if 'you want this to run or' else 'this line fails!'
這是在2.4語法錯誤。
雖然這很聰明,但它非常違背「顯式與隱式」規則。根據這樣的副作用,我感覺不對。從很多問題來看,許多終端用戶從不讀取堆棧跟蹤,只看到「哦,語法錯誤!程序必須被破壞!」 – 2011-06-03 09:03:03
@Tim:哦,我同意這絕對是hacky,但它必須是。請記住,如果您的代碼使用新功能,那麼它將永遠不會編譯爲字節碼,因此您無法查詢sys.version_info等,因爲它不會運行!因此,您需要儘早趕上,向用戶提供稍好的信息。 – 2011-06-03 09:08:41
......儘管像Walter Mundt的回答那樣拆分文件也是一種好方法。我的方法是一種快速和骯髒的方式來做到這一點,而不添加新的文件(加上它很有趣的想法了!) – 2011-06-03 09:21:34
而不是索引你總是可以做到這一點,
import platform
if platform.python_version() not in ('2.6.6'):
raise RuntimeError('Not right version')
這是硬編碼的_specific_版本,而問題是關於_minimum_版本檢查。 – mklement0 2017-06-10 14:43:25
爲了補充現有的,有用的答案:
您可能需要編寫與兩個的Python 2.x的運行腳本和 3.x和要求最低版本爲每個。例如,如果您的代碼使用argparse模塊,則至少需要2.7(使用2.x Python)或至少3.2(使用3.x Python)。
下面的代碼片段實現了這種檢查;唯一需要適應不同的但類似的情況是MIN_VERSION_PY2=...
和MIN_VERSION_PY3=...
分配。
如前所述:這應該是放置在腳本的頂部,在任何其他import
語句之前。
import sys
MIN_VERSION_PY2 = (2, 7) # min. 2.x version as major, minor[, micro] tuple
MIN_VERSION_PY3 = (3, 2) # min. 3.x version
# This is generic code that uses the tuples defined above.
if (sys.version_info[0] == 2 and sys.version_info < MIN_VERSION_PY2
or
sys.version_info[0] == 3 and sys.version_info < MIN_VERSION_PY3):
sys.exit(
"ERROR: This script requires Python 2.x >= %s or Python 3.x >= %s;"
" you're running %s." % (
'.'.join(map(str, MIN_VERSION_PY2)),
'.'.join(map(str, MIN_VERSION_PY3)),
'.'.join(map(str, sys.version_info))
)
)
如果版本不符合要求,像下面的消息被打印到stderr和腳本,退出代碼退出1.
This script requires Python 2.x >= 2.7 or Python 3.x >= 3.2; you're running 2.6.2.final.0.
注:這是一個基本上改寫版本的一個早期的,不必要的複雜的答案,在實現之後 - 歸功於Arkady's helpful answer - 比較運算符(如>
)可以直接應用於元組。
您可以利用的事實,元組進行比較時,Python會做正確的事情:
#!/usr/bin/python
import sys
MIN_PYTHON = (2, 6)
if sys.version_info < MIN_PYTHON:
sys.exit("Python %s.%s or later is required.\n" % MIN_PYTHON)
我需要確保我使用Python 3.5(或最終導致更高)。我自己哼了一聲,然後我想問問SO - 但我沒有留下深刻印象的答案(對不起,你們都:: smile ::)。我沒有放棄,而是提出了下面的方法。我測試過的min_python
和max_python
規範元組的各種組合,它似乎很好地工作:
把這個代碼放到一個__init__.py
是有吸引力的:
__init_p3__.py
,如樣本註釋掉的最後一行所示。 不要忘記用適當的包裝名稱替換pkgname
佔位符。如果你不想分鐘(或最大),只需將其設置爲=()
= (3,)
不要忘了逗號,否則(3)
只是一個括號(簡單)表達式計算到一個單一的int
= (3, 4, 1)
注:我沒有太大的Windoze程序員,所以text_cmd_min
和text_cmd_max
價值取向爲* nix系統。如果您修復了代碼以在其他環境中工作(例如Windoze或某些特定的* Nix變體),請發佈。 (理想情況下,一個超級智能代碼塊將適用於所有環境,但我現在對我的* Nix唯一解決方案感到滿意。)
PS:我對Python有點新,我不喜歡沒有一個版本低於2.7.9.final.0的解釋器,所以測試我的代碼以獲得更早的變體是一件非常困難的事情。另一方面,有人真的在意嗎? (這是一個實際的問題,我有:在什麼(實際ISH)方面,我需要處理口譯的「優雅的錯誤,Python的版本」問題2.7.9之前?)
__init__。 PY
'''Verify the Python Interpreter version is in range required by this package'''
min_python = (3, 5)
max_python = (3,)
import sys
if (sys.version_info[:len(min_python)] < min_python) or (sys.version_info[:len(max_python)] > max_python):
text_have = '.'.join("%s" % n for n in sys.version_info)
text_min = '.'.join("%d" % n for n in min_python) if min_python else None
text_max = '.'.join("%d" % n for n in max_python) if max_python else None
text_cmd_min = 'python' + text_min + ' ' + " ".join("'%s'" % a for a in sys.argv) if min_python else None
text_cmd_max = 'python' + text_max + ' ' + " ".join("'%s'" % a for a in sys.argv) if max_python > min_python else None
sys.stderr.write("Using Python version: " + text_have + "\n")
if min_python: sys.stderr.write(" - Min required: " + text_min + "\n")
if max_python: sys.stderr.write(" - Max allowed : " + text_max + "\n")
sys.stderr.write("\n")
sys.stderr.write("Consider running as:\n\n")
if text_cmd_min: sys.stderr.write(text_cmd_min + "\n")
if text_cmd_max: sys.stderr.write(text_cmd_max + "\n")
sys.stderr.write("\n")
sys.exit(9)
# import pkgname.__init_p3__
與9.0.0版PIP在分配的元數據supportsRequires-Python字段,可以通過帶24-2-0版本setuptools的寫入開始。該功能可通過python_requires
關鍵字參數獲得setup
函數。
例(在setup.py):
setup(
...
python_requires='>=2.5,<2.7',
...
)
要使用此功能一個具有第一包的項目/腳本如果還沒有的優勢。這在典型情況下非常簡單,並且應該儘可能完成,因爲它允許用戶輕鬆安裝,使用和卸載指定的項目/腳本。詳情請參閱Python Packaging User Guide。
另請參閱http://stackoverflow.com/questions/3035749/how-to-write-a-python-2-6-script-that-gracefully-fails-with-older-python和http:// stackoverflow .com/questions/388069/python-graceful-future-feature-future-import – 2011-06-03 08:50:07
答案*您*接受http://stackoverflow.com/questions/3035749不使用新的異常處理。 – Johnsyweb 2011-06-03 09:31:57
更新(2016年10月29日):現在setuptools和pip支持'python_requires'關鍵字到'setup'函數 - 請參閱我的[answer](http://stackoverflow.com/a/40300957/95735)。 – 2016-10-28 08:27:41