处理Python 2.4中的上下文类 [英] Dealing with context classes in Python 2.4

查看:107
本文介绍了处理Python 2.4中的上下文类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用python-daemon模块.它提供daemon.DaemonContext类以正确地守护脚本.尽管我的主要目标是Python 2.6+,但我想保持与2.4版的向后兼容性.

I'm trying to use the python-daemon module. It supplies the daemon.DaemonContext class to properly daemonize a script. Although I'm primarily targeting Python 2.6+, I'd like to maintain backwards compatibility to version 2.4.

Python 2.5支持从未来导入上下文,但是Python 2.4没有这样的功能. 我以为我可以捕捉到with语句引发的任何错误,并手动为2.4输入和退出上下文,但是我似乎无法捕捉到引发的SyntaxError.

Python 2.5 supports importing contexts from future, but Python 2.4 has no such facility. I figured I could just catch whatever error the with statement raises and enter and exit the context manually for 2.4, but I can't seem to catch the SyntaxError raised.

除了显式检查解释器版本以外,还有什么方法可以完成? 以下是我要做的事情和遇到的问题的要点.在现实生活中,我没有上下文类的控制权,因此它需要在不破坏原始类的情况下工作,即不像

Is there any way to accomplish this short of explicitly checking the interpreter version? Below is the gist of what I'm trying to do and the problem I'm getting. In Real Life I don't have control of the context class, so it needs to work without mangling the original class, ie not like these ideas.

没关系,如果Python 2.4无法运行python-daemon;我至少希望能够捕获错误并实施后备之类的功能.

Nevermind if Python 2.4 can't run python-daemon; I'd at least like to able to catch the error and implement a fallback or something.

感谢您的帮助.

#!/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)

推荐答案

SyntaxError在编译时被Python编译器诊断-您大概是在尝试从作为编译器一部分进行编译的代码中捕获"它相同的模块(例如,这就是您在代码示例中所做的事情),因此它当然不起作用-您的捕获"代码尚未编译(因为编译未成功终止),因此它无法抓住任何东西.

SyntaxError is diagnosed by the Python compiler as it compiles -- you're presumably trying to "catch" it from code that's being compiled as part of the same module (e.g., that's what you're doing in your code sample), so of course it won't work -- your "catching" code hasn't been compiled yet (because compilation has terminated unsuccessfully) so it can't catch anything.

您需要确保可能比语法代码更早地编译可能有语法错误的代码–将其放在您在try子句中导入的单独模块中,或者在compile具有该名称的内置字符串(如果成功终止,则可以稍后执行compile调用产生的字节码).

You need to ensure the code that might have a syntax error gets compiled later than the catching code -- either put it in a separate module that you import in the try clause, or in a string you compile with the built-in by that name (you can later execute the bytecode resulting from the compile call, if it terminates successfully).

我认为,这两种可能性都不适合您的目的.不幸的是,我怀疑使用两个单独的模块(可能根据是否执行此编译"检查而在它们之间进行选择,但是对我来说版本检查听起来更干净)是唯一的干净"解决方案.

Neither possibility looks good for your purposes, I think. I suspect that using two separate modules (and probably picking between them depending on the "does this compile" check, but a version check sounds much cleaner to me) is the only "clean" solution, unfortunately.

编辑:以下是对基准检查进行微基准测试/例外的方法:

Edit: here's how to microbenchmark try/except against version checks:

$ 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核心开发人员专注于促进和鼓励他们喜欢的结构的使用,而不是他们不喜欢的结构的使用.

As you see, the version I consider cleaner is 10.8 / 0.221, almost 50 times faster, on 2.4, and 40.5 / 0.156, almost 260 times faster, on 2.6. In general (with rare exceptions), the clean (i.e., "pythonic") approach will turn out to be the better optimized one in Python -- often, at least part of the reason can be that Python core developers focus on facilitating and encouraging the use of constructs they like, rather than that of constructs they dislike.

这篇关于处理Python 2.4中的上下文类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆