2

python-daemonモジュールを使おうとしています。スクリプトを適切にデーモン化するためのdaemon.DaemonContextクラスを提供します。私は主にPython2.6以降を対象としていますが、バージョン2.4との下位互換性を維持したいと考えています。

Python 2.5はfutureからのコンテキストのインポートをサポートしていますが、Python2.4にはそのような機能はありません。withステートメントで発生したエラーをキャッチし、2.4のコンテキストを手動で開始および終了できると思いましたが、発生したSyntaxErrorをキャッチできないようです。

インタプリタのバージョンを明示的にチェックする以外に、これを達成する方法はありますか?以下は、私がやろうとしていることの要点と私が直面している問題です。実生活では、コンテキストクラスを制御できないため、元のクラスを操作せずに機能する必要があります。つまり、これらのアイデアは好きではありません。

Python2.4がpython-daemonを実行できないかどうかは気にしないでください。少なくとも、エラーをキャッチしてフォールバックなどを実装できるようにしたいと思います。

助けてくれてありがとう。

#!/usr/bin/python2.4
from __future__ import with_statement
# with_statement isn't in __future__ in 2.4.
# In interactive mode this raises a SyntaxError.
# During normal execution it doesn't, but I wouldn't be able to catch it
# anyways because __future__ imports must be at the beginning of the file, so
# that point is moot.


class contextable(object):
    def __enter__(self):
        print('Entering context.')
        return None
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('Exiting context.')
        return False

def spam():
    print('Within context.')

context = contextable()

try:
    with context: # This raises an uncatchable SyntaxError.
        spam()
except SyntaxError, e: # This is how I would like to work around it.
    context.__enter__()
    try:
        spam()
    finally:
        context.__exit__(None, None, None)
4

1 に答える 1

3

SyntaxErrorは、コンパイル時にPythonコンパイラによって診断されます。おそらく、同じモジュールの一部としてコンパイルされているコードから「キャッチ」しようとしているので(たとえば、コードサンプルで実行していることです)。それは機能しません-あなたの「キャッチ」コードはまだコンパイルされていないので(コンパイルが失敗して終了したため)、何もキャッチできません。

構文エラーが発生する可能性のあるコードが、キャッチコードよりも後でtryコンパイルされるようにする必要があります。つまり、句にインポートする別のモジュールに配置するかcompile、その名前で組み込みの文字列に配置します(compile正常に終了した場合、後で呼び出しの結果のバイトコードを実行できます)。

どちらの可能性もあなたの目的には良くないと思います。残念ながら、2つの別々のモジュールを使用する(そしておそらく「このコンパイルを行う」チェックに応じてモジュールを選択するが、バージョンチェックは私にははるかにクリーンに聞こえる)ことが唯一の「クリーンな」ソリューションだと思います。

編集:バージョンチェックに対してtry/exceptをマイクロベンチマークする方法は次のとおりです。

$ python2.4 -mtimeit 'try:
  compile("with x: pass", "", "exec")
except SyntaxError: x=1
else: x=2'
100000 loops, best of 3: 10.8 usec per loop
$ python2.6 -mtimeit 'try:
  compile("with x: pass", "", "exec")
except SyntaxError: x=1
else: x=2'
10000 loops, best of 3: 40.5 usec per loop

$ python2.4 -mtimeit -s'import sys' 'if sys.version>="2.5": x=2
else: x=1'
1000000 loops, best of 3: 0.221 usec per loop
$ python2.6 -mtimeit -s'import sys' 'if sys.version>="2.5": x=2
else: x=1'
10000000 loops, best of 3: 0.156 usec per loop

ご覧のとおり、私がよりクリーンだと考えるバージョンは10.8 / 0.221、2.4ではほぼ50倍高速であり40.5 / 0.156、2.6ではほぼ260倍高速です。一般に(まれな例外を除いて)、クリーンな(つまり、「pythonic」)アプローチは、Pythonでより最適化されたアプローチであることがわかります。多くの場合、理由の少なくとも一部は、Pythonコア開発者が促進と奨励に焦点を合わせていることです。嫌いな構成ではなく、好きな構成を使用する。

于 2010-08-19T03:29:00.413 に答える