web-dev-qa-db-ja.com

古いインタープリターバージョンが原因で失敗した将来の機能(__future__)のインポートを適切に処理する方法

失敗した将来の機能のインポートをどのように適切に処理しますか?ユーザーがPython 2.5を使用して実行しており、私のモジュールの最初のステートメントが次の場合:

from __future__ import print_function

Python 2.5でこのモジュールをコンパイルすると、次のように失敗します。

  File "__init__.py", line 1
    from __future__ import print_function
SyntaxError: future feature print_function is not defined

Python> = 2.6でプログラムを再実行する必要があることをユーザーに通知し、それを行う方法に関する指示を提供することもできます。ただし、引用するには PEP 236

Future_statementの前に表示できる行は次のとおりです。

  • モジュールのdocstring(もしあれば)。
  • コメント。
  • 空白行。
  • その他のfuture_statements。

だから私は次のようなことはできません:

import __future__

if hasattr(__future__, 'print_function'):
    from __future__ import print_function
else:
    raise ImportError('Python >= 2.6 is required')

次の結果が得られるため:

  File "__init__.py", line 4
    from __future__ import print_function
SyntaxError: from __future__ imports must occur at the beginning of the file

PEPの次のスニペットは、インラインで実行することを希望しているようです。

Q:future_statementsをtry/exceptブロックでラップしたいので、実行しているPythonのバージョンに応じて異なるコードを使用できます。なぜできないのですか?

A:ごめんなさい! try/exceptはランタイム機能です。 future_statementsは主にコンパイル時の仕掛けであり、try/exceptはコンパイラが完了してからずっと後に発生します。つまり、try/exceptを実行するまでに、モジュールに有効なセマンティクスはすでに完了しています。 try/exceptは、looksを成し遂げるべきではないため、単に許可されません。また、これらの特別なステートメントを見つけやすく、認識しやすくしたいと考えています。

can直接__future__をインポートし、その中の情報をsys.version_infoと一緒に使用して、実行しているリリースがどこにあるかを把握することに注意してください。特定の機能のステータスに関連して立っています。

アイデア?

68
cdleary

「Python> = 2.6を使用してプログラムを再実行する必要があることをユーザーに通知し、その方法についての指示を提供したいです。」

READMEファイルは何のためですか?

これがあなたの代替案です。 「ラッパー」:ターゲットaopを実行する前に環境をチェックするPythonの小さなblob。

ファイル:appwrapper.py

import sys
major, minor, micro, releaselevel, serial = sys.version_info
if (major,minor) <= (2,5):
    # provide advice on getting version 2.6 or higher.
    sys.exit(2)
import app
app.main()

「直接インポート」の意味。 __future__の内容を調べることができます。 from __future__ import print_functionはコンパイラーへの情報であるという事実に縛られていますが、実際の作業を行うモジュールをインポートする前にいろいろと調べることができます。

import __future__, sys
if hasattr(__future__, 'print_function'): 
    # Could also check sys.version_info >= __future__. print_function.optional
    import app
    app.main()
else:
    print "instructions for upgrading"
59
S.Lott

以前に使用したかなりハック的で簡単な方法は、バイトリテラルがPython 2.6で導入され、ファイルの先頭近くで次のようなものを使用するという事実を利用することです。

b'This module needs Python 2.6 or later. Please do xxx.'

これはPython 2.6以降では無害ですが、以前のバージョンではSyntaxErrorです。ファイルをコンパイルしようとすると、エラーが発生しますが、メッセージも表示されます。与えたい。

from __future__ import print_functionの後にこの行が必要になるため、SyntaxErrorを生成するのはインポートであり、有用なエラーメッセージは表示されませんが、奇妙なことに後のエラーが優先されます。インポートからのエラー自体は実際には構文エラーではないため、最初のコンパイルパスでは発生しないため、実際の構文エラーが最初に発生するのではないかと思います(ただし、推測しています)。

これは「優雅」であるという基準を満たさない可能性があり、非常にPython 2.6固有ですが、すばやく簡単に実行できます。

46
Scott Griffiths

次のように、"from __future__ import ..."と同じ行にコメントを追加するだけです。

from __future__ import print_function, division  # We require Python 2.6 or later

Pythonはエラーを含む行を表示するため、Python 2.5でモジュールを実行しようとすると、わかりやすい説明的なエラーが表示されます。

    from __future__ import print_function, division  # We require Python 2.6 or later
SyntaxError: future feature print_function is not defined
40
Dave Burton