245

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

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

たとえば、三項演算子 (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

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

4

18 に答える 18

115

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

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

また、 Python 2.5with でも利用できます。追加するだけ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 *
于 2009-01-15T08:50:17.690 に答える
107

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

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 インタープリターを使用している人々に遭遇する予定がある場合は、 の使用を検討することもできますが、正規表現を使用する必要があります。

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

于 2009-01-15T09:26:51.143 に答える
34

試す

輸入プラットフォーム
platform.python_version()

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

于 2009-01-15T08:55:44.357 に答える
22

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

import sys
if sys.hexversion < 0x02060000:
    print "yep!"
else:
    print "oops!"
于 2010-06-28T12:38:59.043 に答える
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")
于 2015-06-25T13:39:04.657 に答える
7

下位互換性を維持するために、セットは Python 2.4 のコア言語の一部になりました。私は当時これを行いました。これはあなたにも役立ちます:

if sys.version_info < (2, 4):
    from sets import Set as set
于 2009-01-15T09:43:38.877 に答える
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

于 2011-10-04T01:52:20.950 に答える
2

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

上記のように、必要に応じて eval を使用して、コンパイル ステップを延期し、実行時に 1 行のコードでそれを行うことができますが、Python が潜在的に実行される可能性があるため、私は個人的にはそれを避けることを好みます。不必要なランタイム コンパイルは、1 つの理由として、また別の理由として、コードの乱雑さのように感じられるものを作成します。(必要に応じて、コードを生成するコードを生成するコードを生成することもできます。そして、今から 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 の使用をサポートします。

于 2011-09-13T02:27:02.737 に答える
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...
于 2015-10-23T11:19:29.907 に答える
1

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

例えば:

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

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

于 2009-01-15T08:51:22.290 に答える
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") )

はい、最終的なデコード/ストリップ行がひどいことは知っていますが、バージョン番号をすばやく取得したかっただけです。私はそれを洗練するつもりです。

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

于 2012-05-09T16:11:57.753 に答える
-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
于 2009-09-14T22:00:06.313 に答える
-3

問題は非常に単純です。バージョンが以下ではなく、 2.4未満であるかどうかを確認しました。したがって、Python のバージョンが 2.4 の場合、2.4 以上です。あなたが持っているべきだったのは:

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

、 いいえ

    if sys.version_info < (2, 4):
于 2010-04-09T19:31:02.303 に答える