新しい言語機能を使用するプログラムでPythonのバージョンを確認するにはどうすればよいですか?


239

特定のバージョンのPythonを必要とするPythonスクリプトがある場合、以前のバージョンのPythonを使用してスクリプトを起動したときに正常に失敗する正しい方法は何ですか?

エラーメッセージを発行して終了するのに十分早い段階で制御を取得するにはどうすればよいですか?

たとえば、3項演算子(2.5の新機能)と「with」ブロック(2.6の新機能)を使用するプログラムがあります。私は、スクリプトが最初に呼び出す簡単なインタープリターバージョンチェッカールーチンを記述しましたが、それほど遠くはありません。代わりに、私のルーチンが呼び出される前に、Pythonコンパイル中にスクリプトが失敗します。したがって、スクリプトのユーザーには、非常にあいまいなsynaxエラートレースバックが表示されます。これは、Pythonの誤ったバージョンを実行している場合にのみ当てはまると専門家が推測する必要があります。

Pythonのバージョンを確認する方法を知っています。問題は、古いバージョンのPythonでは一部の構文が不正であることです。このプログラムを考えてみましょう:

import sys
if sys.version_info < (2, 4):
    raise "must use python 2.5 or greater"
else:
    # syntax error in 2.4, ok in 2.5
    x = 1 if True else 2
    print x

2.4で実行すると、この結果が欲しい

$ ~/bin/python2.4 tern.py 
must use python 2.5 or greater

この結果ではありません:

$ ~/bin/python2.4 tern.py 
  File "tern.py", line 5
    x = 1 if True else 2
           ^
SyntaxError: invalid syntax

(同僚のチャネリング。)


3
「Pythonのバージョンを確認してください。問題は、古いバージョンのPythonでは一部の構文が不正であることです。」これがどのように問題なのかわかりません。バージョンを確認できれば、構文エラーを回避できます。バージョンチェックは構文にどのように適用されませんか?質問を明確にできますか?
S.Lott、2009年

4
@ S.Lottいいえ、間違いありません。コードが読み込まれず(解析されず)実行されない場所にコードを含めることが困難なだけです。これは答えが示すようにすぐにはわかりません。
ブレンダン

7
S.Lott、コンパイルされないため、古いバージョンのpythonではテストを実行できません。代わりに、一般的な構文エラーが発生します。2.4インタープリターでサンプルコードを試してみると、バージョンテストに到達できないことがわかります。
Mark Harrison

7
@ S.Lottまあ、それはあなたが取るに足りないと思うことに依存します-個人的には、異なるバージョンのPythonのために個別のファイルを作成したり、些細な追加のプロセスを生成したりすることは考えません。私はこの質問は価値があると思います、特にPythonがきちんとした、そしてしばしば驚くべきトリックでいっぱいであると考えるとき-私はきちんとした答えがあったかどうか知りたいと思ってGoogleからここに来ました
ブレンダン

7
私たちはこの議論の終わりに到達したと思います。どうすればいいのかわからないことを質問したところ、どうすればいいのか答えてもらいました。私は何も提案していません。oripの回答を受け入れました。これは私(実際には私がチャネリングしている同僚)にとって非常に効果的です。Viva Leスタックオーバーフロー!
Mark Harrison

回答:


111

次を使用してテストできますeval

try:
  eval("1 if True else 2")
except SyntaxError:
  # doesn't have ternary

また、with あるのPython 2.5で、ちょうど追加利用できますfrom __future__ import with_statement

編集:十分に早く制御を取得するに.pyは、インポートする前に(たとえば__init__.py、パッケージ内で)異なるファイルに分割し、メインファイルの互換性を確認します。

# __init__.py

# Check compatibility
try:
  eval("1 if True else 2")
except SyntaxError:
  raise ImportError("requires ternary support")

# import from another module
from impl import *

10
これは素晴らしい答えです。アドレッシングが必要な質問の主な問題は、プログラムがそのバージョンのpythonの実行を開始するために構文的に正しい必要があるため、新しい構文を使用すると、プログラムが古いバージョンのインタープリターで起動できなくなることです。evalはそれを回避します
Autoplectic 2009年

7
パッケージがsetuptoolsによってインストールされている場合、ソースファイルのバイトコンパイルは失敗します。また、実行時エラーメッセージを生成するためのすべてのゆがみは少し無意味に見えます。なぜ要件を文書化し、そのままにしないのですか?
John Machin、

2
単純なステートメントではなく式をチェックする場合は、のexec代わりにを使用する必要があることに注意してくださいeval。これは、py2kとpy3kの両方でstderrに出力する関数を作成しようとしたときに発生しました。
Xiong Chiamiov 2010年

2
このソリューションのよりクリーンなバージョンは、「チェック」を別のモジュールに入れてインポ​​ートすることです(importステーションをtry / exceptでラップします)。ほかにも確認する必要がある場合があることに注意してくださいSyntaxError(組み込み関数や標準ライブラリへの追加など)
Steven

103

次のことを行うプログラムのラッパーを用意します。

import sys

req_version = (2,5)
cur_version = sys.version_info

if cur_version >= req_version:
   import myApp
   myApp.run()
else:
   print "Your Python interpreter is too old. Please consider upgrading."

sys.version()2.0より前のPythonインタープリターを使用している人に出会う予定があるが、いくつかの正規表現を使用する必要がある場合は、の使用を検討することもできます。

そして、これを行うためのよりエレガントな方法があるかもしれません。


7
参考までに、「cur_version> = req_version」は条件として機能するはずです。
09

4
sys.version_info関数ではありません。
nh2

3
このように成功した条件付きの中にコードを配置することは、インデントとロジックの追加が不要であるため、かなり悪い習慣です。a:if sys.version_info [:2] <req_version:print "old"; sys.exit()-それ以外の場合は通常どおり続行します。
timss 2013

1
Tim Petersが "The Zen of Python"で言うように: "フラットはネストよりも優れています。" (これはpythonで「これをインポート」と入力すると確認できます)
クリストファーシュロバ'27年

1
@ChristopherShrobaありがとうございますimport this。素敵な気晴らし。
サミュエルハーマー

32

試す

インポートプラットフォーム
platform.python_version()

「2.3.1」のような文字列が表示されます。これが正確に必要でない場合は、「プラットフォーム」ビルトインを介して利用できる豊富なデータセットがあります。あなたが欲しいものはどこかにあるはずです。


4
-1:更新された質問で説明されているように、これは機能しません。新しいバージョンのPythonの構文を使用すると、ファイルはコンパイルされません。コンパイルされない場合、ファイルを実行してバージョンを確認することはできません。
スコットグリフィス

1
@ScottGriffithsのprint(platform.python_version())代わりに実行platform.python_version()
Suriyaa 2016年

@ScottGriffithsまた、私の答えをチェックアウトしてください:stackoverflow.com/a/40633458/5157221
Suriyaa 2016年

22

おそらく、このバージョン比較を行う最善の方法は、を使用することsys.hexversionです。バージョンタプルを比較しても、すべてのpythonバージョンで望ましい結果が得られるわけではないため、これは重要です。

import sys
if sys.hexversion < 0x02060000:
    print "yep!"
else:
    print "oops!"

これは最もエレガントだと思いますが、他の開発者が理解するのはおそらく最も簡単ではありません。
Nick Bolton

5
バージョンのタプルを比較すると望ましい結果が得られない状況を説明できますか?
SpoonMeiser、2012年

バージョンタプルには英数字の値も含めることができます。
ソリン2012年

8
-1:更新された質問で説明されているように、これは機能しません。新しいバージョンのPythonの構文を使用すると、ファイルはコンパイルされません。コンパイルされない場合、ファイルを実行してバージョンを確認することはできません。
スコットグリフィス

これはどのバージョン/プラットフォームで失敗しますか?
ソリン2016

15
import sys    
# prints whether python is version 3 or not
python_version = sys.version_info.major
if python_version == 3:
    print("is python 3")
else:
    print("not python 3")

7
Python 2.6以下でsys.version_infoは、は名前付きタプルではないことに注意してください。sys.version_info[0]メジャーバージョン番号とsys.version_info[1]マイナーバージョンに使用する必要があります。
coredumperror

9

でNykakinから回答AskUbuntu

platform標準ライブラリのモジュールを使用して、コード自体からPythonのバージョンを確認することもできます。

2つの機能があります。

  • platform.python_version() (文字列を返します)。
  • platform.python_version_tuple() (タプルを返します)。

Pythonコード

例えば、ファイルを作成します。version.py

バージョンを確認する簡単な方法:

import platform

print(platform.python_version())
print(platform.python_version_tuple())

evalメソッドを使用することもできます:

try:
  eval("1 if True else 2")
except SyntaxError:
  raise ImportError("requires ternary support")

コマンドラインでPythonファイルを実行します。

$ python version.py 
2.7.11
('2', '7', '11')

Windows 10上のWAMPサーバーを介したPythonとCGIの出力:

スクリーンショット2016-11-16 14.39.01 by Suriyaa Kudo


役立つリソース


7

セットは、後方互換性を維持するために、Python 2.4のコア言語の一部になりました。私はそのときこれをしました、それはあなたのためにも働きます:

if sys.version_info < (2, 4):
    from sets import Set as set

3
バージョンの代わりに機能をチェックするほうがいいですよね?try: set except NameError: from sets import Set as set
orip

@orip:なぜですか?このセットのように、機能が導入されているバージョンがわかっている場合は、上記のコードを使用してください。何も問題ありません。
アンドレ

7

問題は次のとおりですが、エラーメッセージを発行して終了するのに十分早い段階で制御を取得するにどうすればよいですか

私が答える質問は次のとおりですアプリを起動する前にエラーメッセージを発行するのに十分早く制御するにどうすればよいですか?

他の投稿とはかなり違う答えができます。これまでの答えはPython内からあなたの質問を解決しようとしているようです。

私は、Pythonを起動する前にバージョンチェックを行うと言います。あなたの道はLinuxまたはunixであると思います。ただし、Windowsスクリプトしか提供できません。私はそれをlinuxのスクリプト構文に適合させることをイメージしていますが、それほど難しくありません。

バージョン2.7のDOSスクリプトは次のとおりです。

@ECHO OFF
REM see http://ss64.com/nt/for_f.html
FOR /F "tokens=1,2" %%G IN ('"python.exe -V 2>&1"') DO ECHO %%H | find "2.7" > Nul
IF NOT ErrorLevel 1 GOTO Python27
ECHO must use python2.7 or greater
GOTO EOF
:Python27
python.exe tern.py
GOTO EOF
:EOF

これはアプリケーションのどの部分も実行しないため、Python例外は発生しません。一時ファイルの作成やOS環境変数の追加は行われません。また、バージョンの構文規則が異なるため、アプリが例外で終了することはありません。これは、アクセスのセキュリティポイントとして考えられる可能性が3つ少なくなります。

FOR /Fラインが鍵となります。

FOR /F "tokens=1,2" %%G IN ('"python.exe -V 2>&1"') DO ECHO %%H | find "2.7" > Nul

複数のpythonバージョンについては、次のURLを確認してください。http//www.fpschultze.de/modules/smartfaq/faq.php? faqid = 17

そして私のハックバージョン:

[MSスクリプト; PythonバージョンはPythonモジュールの事前起動を確認します] http://pastebin.com/aAuJ91FQ


これらの反対票については、その理由を恐れずに説明してください。
DevPlayer

まさに探していました。ありがとう!%% Hは?
クロッカー

@Clocker python.exe -Vは "Python 2.7"文字列を返します。コンソールは "Python"文字列を%% Gに入れ、 "2.7"文字列を自動的に作成されたos var %% H(Gの次の文字)に入れます。エコー%% H | DOSコマンドに「2.7」パイプ「2.7」を検索「2.7」で%% Hが見つかった場合にエラーレベルを1に設定する「2.7」を検索 DOSのfindコマンドを使用して1になったそのエラーレベルにより、DOSバッチラベルに分岐できます:Python27
DevPlayer

3
import sys
sys.version

このような答えを得るでしょう

'2.7.6(デフォルト、2016年10月26日20:30:19)\ n [GCC 4.8.4]'

ここで2.7.6はバージョンです


2

上記のように、構文エラーは実行時ではなくコンパイル時に発生します。Pythonは「解釈された言語」ですが、Pythonコードは実際には直接解釈されません。バイトコードにコンパイルされ、解釈されます。モジュールがインポートされたときに発生するコンパイル手順があり(.pycまたは.pydファイルの形式で使用できるコンパイル済みのバージョンがない場合)、エラーが発生したときであり、(正確に)ときではありません。コードが実行されています。

上記のようにevalを使用することで、コンパイルステップを延期し、実行時に1行のコードで実行させることができますが、Pythonが潜在的に実行される原因となるため、私は個人的にはそれを避けたいと考えています。不必要なランタイムコンパイルは、ある意味で、別の点では、コードの混乱のように感じます。(必要に応じて、コードを生成するコードを生成するコードを生成することができます-そして、6か月後にそれを修正し、デバッグするのに非常に素晴らしい時間を過ごすことができます。)では、代わりに、次のようなものをお勧めします。

import sys
if sys.hexversion < 0x02060000:
    from my_module_2_5 import thisFunc, thatFunc, theOtherFunc
else:
    from my_module import thisFunc, thatFunc, theOtherFunc

..新しい構文を使用する関数が1つしかなく、それが非常に短い場合でも、これを実行します。(実際、そのような関数の数とサイズを最小限に抑えるためにあらゆる妥当な手段を講じます。その構文の1行でifTrueAElseB(cond、a、b)のような関数を書くことさえできます。)

指摘する価値があるかもしれないもう1つのことは(まだ誰も指摘していないことに少し驚いています)、以前のバージョンのPythonは次のようなコードをサポートしていませんでした

value = 'yes' if MyVarIsTrue else 'no'

..それはのようなコードをサポートしました

value = MyVarIsTrue and 'yes' or 'no'

それが三元表現の古い書き方でした。私はまだPython 3をインストールしていませんが、私の知る限り、その「古い」方法は今でも機能します。必要に応じて、新しい構文を条件付きで使用する価値があるかどうかを自分で決めることができます古いバージョンのPythonの使用をサポートします。


2
マジ?いくつかのマイナーな構造を変更できるように、コードを複製しますか?ああ。とても残念。そしてのa and b or c代わりにb if a else c、それは同等ではありません。場合bfalsyあり、それは生産、失敗するaのではなくb
Chris Morgan、

1
コードを複製することはお勧めしません。バージョン固有のコードのラッパー関数を作成し、そのシグネチャがバージョン間で変化しないようにし、それらの関数をバージョン固有のモジュールに配置することをお勧めします。私は多分1から5行の長さの関数について話している。aとbまたはcは、bがfalseと評価される場合にa else cの場合、bと同じではないことは事実です。ですから、common_ops_2_4.pyのifAThenBElseC(a、b、c)は、1行ではなく2行または3行にする必要があると思います。
Shavais

2

以下をファイルの最上部に配置します。

import sys

if float(sys.version.split()[0][:3]) < 2.7:
    print "Python 2.7 or higher required to run this code, " + sys.version.split()[0] + " detected, exiting."
    exit(1)

次に、通常のPythonコードを続行します。

import ...
import ...
other code...

1
むしろ使用sys.version_info < (2, 7)
Antti Haapala

@AnttiHaapalaこれは私にとって完璧です、sys.version_infoタイプとタプルを比較することがうまくいく理由を説明できますか?
jjj 2016

@jjj sys.version_info にするために使用タプル。例えば(2, 4, 6, 'final', 0); Python 3と2.7でのみ、それは別の型に変更されましたが、それでもタプルと同等です。
Antti Haapala 2016

@AnttiHaapala私は私のアプローチよりもそのアプローチが好きです...ありがとう!
jml

1

バージョンではなく機能をテストするのが最善の方法だと思います。場合によっては、これはささいなことですが、そうでない場合もあります。

例えば:

try :
    # Do stuff
except : # Features weren't found.
    # Do stuff for older versions.

try / exceptブロックを十分に使用している限り、ほとんどのベースをカバーできます。


2
あなたが正しい。それが彼がどのように行うかを尋ねたものです-バージョンYの機能のテストは、バージョンXのバイトコードにコンパイルできないこともあるため、直接行うことはできません。
09年

1

私は問題を自分で解決しようとしているときに簡単な検索の後にこの質問を見つけただけで、上記のいくつかの提案に基づいてハイブリッドを考え出しました。

ラッパースクリプトを使用するというDevPlayerのアイデアは好きですが、欠点は、異なるOSに対して複数のラッパーを維持することになるため、Pythonでラッパーを作成することを決定しましたが、同じ基本的な「exeを実行してバージョンを取得する」ロジックを使用しますこれを思いついた。

2.5以降で動作するはずです。これまでに、Linuxでは2.66、2.7.0、3.1.2、OS Xでは2.6.1でテストしました。

import sys, subprocess
args = [sys.executable,"--version"]

output, error = subprocess.Popen(args ,stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()
print("The version is: '%s'"  %error.decode(sys.stdout.encoding).strip("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLMNBVCXZ,.+ \n") )

はい、最終的なデコード/ストリップラインが恐ろしいことはわかっていますが、バージョン番号をすばやく取得したいと思っていました。それを改善します。

これは今のところ私には十分に機能しますが、誰かがそれを改善できる場合(またはそれがひどいアイデアである理由を教えてください)、それもクールです。


1

以下のために、スタンドアロン Pythonスクリプト、Pythonのバージョン(ここではv2.7.x)を強制するには、次のモジュールのドキュメンテーション文字列のトリックは(* NIX上でテスト)動作します。

#!/bin/sh
''''python -V 2>&1 | grep -q 2.7 && exec python -u -- "$0" ${1+"$@"}; echo "python 2.7.x missing"; exit 1 # '''

import sys
[...]

これは不足しているpython実行可能ファイルも処理するはずですが、grepに依存しています。背景については、こちらをご覧ください。


0

sys.hexversionまたはで確認できsys.version_infoます。

sys.hexversionこれは16進数であるため、あまり人間に優しくありません。sys.version_infoタプルなので、より人間に優しいです。

Python 3.6以降を確認するにはsys.hexversion

import sys, time
if sys.hexversion < 0x30600F0:
    print("You need Python 3.6 or greater.")
    for _ in range(1, 5): time.sleep(1)
    exit()

Python 3.6以降を確認するにはsys.version_info

import sys, time
if sys.version_info[0] < 3 and sys.version_info[1] < 6:
    print("You need Python 3.6 or greater.")
    for _ in range(1, 5): time.sleep(1)
    exit()

sys.version_infoより人間に優しいですが、より多くのキャラクターを必要とします。sys.hexversion人にやさしいとは言えませんが、私はお勧めします。

これがお役に立てば幸いです。


0

Pythonスクリプトがコンパイルされる前に役立つメッセージを出力するakhanの優れた答えをさらに詳しく説明します。

スクリプトがPython 3.6以降で実行されていることを確認するには、次の2行をPythonスクリプトの先頭に追加します。

#!/bin/sh
''''python3 -c 'import sys; sys.exit(sys.version_info < (3, 6))' && exec python3 -u -- "$0" ${1+"$@"}; echo 'This script requires Python 3.6 or newer.'; exit 1 # '''

(注:2行目は4つの一重引用符で始まり、3つの一重引用符で終わります。これは奇妙に見えるかもしれませんが、タイプミスではありません。)

このソリューションの利点は、3.6よりも古いバージョンのPythonを使用しても、のようなコードprint(f'Hello, {name}!')が原因にSyntaxErrorならないことです。代わりに、この役立つメッセージが表示されます。

This script requires Python 3.6 or newer.

もちろん、このソリューションは、Unixのようなシェルでのみ機能し、スクリプトが直接呼び出された場合(例./script.py:)、および適切なeXecuteアクセス許可ビットが設定されている場合にのみ機能します。


-2

これはどう:

import sys

def testPyVer(reqver):
  if float(sys.version[:3]) >= reqver:
    return 1
  else:
    return 0

#blah blah blah, more code

if testPyVer(3.0) == 1:
  #do stuff
else:
  #print python requirement, exit statement

5
-1:更新された質問で説明されているように、これは機能しません。新しいバージョンのPythonの構文を使用すると、ファイルはコンパイルされません。コンパイルされない場合、ファイルを実行してバージョンを確認することはできません。
スコットグリフィス

-3

問題は非常に簡単です。バージョンだった場合は、確認未満、2.4以上または等しいです。したがって、Pythonのバージョンが2.4の場合、それは2.4以上です。あなたが持っているべきだったのは:

    if sys.version_info **<=** (2, 4):

ではなく

    if sys.version_info < (2, 4):

4
パラグラフ3と更新をお読みください。新しい言語構造を使用している場合、コードは2.4でコンパイルされないため、このコードを実行する必要はありません。
マークハリソン

未満は大丈夫で、評価を逃しただけです。
Craig
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.