Работа с классами контекста в Python 2.4 - PullRequest
2 голосов
/ 19 августа 2010

Я пытаюсь использовать модуль python-daemon.Он предоставляет класс daemon.DaemonContext для правильной демонизации скрипта.Хотя я в первую очередь ориентируюсь на Python 2.6+, я бы хотел поддерживать обратную совместимость с версией 2.4.

Python 2.5 поддерживает импорт контекстов из future , но в Python 2.4 такой возможности нет.Я подумал, что могу просто перехватить любую ошибку, которую вызывает оператор with, и ввести и выйти из контекста вручную для 2.4, но, похоже, я не могу отловить поднятое SyntaxError.

Есть ли способ сделать это явнопроверять версию переводчика?Ниже суть того, что я пытаюсь сделать, и проблема, которую я получаю.В реальной жизни у меня нет контроля над классом контекста, поэтому он должен работать без искажения исходного класса, то есть не как этих идей.

Неважно, если Python 2.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)

1 Ответ

3 голосов
/ 19 августа 2010

SyntaxError диагностируется компилятором Python во время его компиляции - вы, вероятно, пытаетесь «поймать» его из кода, который компилируется как часть того же модуля (например, это то, что вы делаете в своем кодепример), поэтому, конечно, это не сработает - ваш «перехватывающий» код еще не скомпилирован (потому что компиляция завершилась неудачно), поэтому он не может ничего перехватить.

Необходимо убедиться, чтокод, который может иметь синтаксическую ошибку, компилируется на позже , чем код перехвата - либо поместите его в отдельный модуль, который вы импортируете в предложении try, либо в строку, которую вы compile создаете-в этом имени (позже вы можете выполнить байт-код, полученный в результате вызова compile, если он успешно завершится).

Я думаю, что ни одна из этих возможностей не подходит для ваших целей.Я подозреваю, что использование двух отдельных модулей (и, вероятно, выбор между ними в зависимости от проверки «делает ли это компиляция», но проверка версии звучит для меня чище), к сожалению, является единственным «чистым» решением.

Редактировать : вот как пробовать микробенчмарк пробовать / исключать проверки версий:

$ 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, почти в 50 раз быстрее, на 2,4 и40.5 / 0.156, почти в 260 раз быстрее, на 2,6.В целом (за редкими исключениями) чистый (то есть «питонический») подход окажется лучше оптимизированным в Python - часто, по крайней мере, одна из причин может заключаться в том, что разработчики ядра Python сосредоточены на содействии и поощрениииспользование конструкций, которые им нравятся, а не конструкции, которые им не нравятся.

...