Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python2.4中处理上下文类_Python_Backwards Compatibility_With Statement - Fatal编程技术网

在Python2.4中处理上下文类

在Python2.4中处理上下文类,python,backwards-compatibility,with-statement,Python,Backwards Compatibility,With Statement,我正在尝试使用python守护进程模块。它提供daemon.DaemonContext类来正确地守护脚本。虽然我主要针对Python2.6+,但我希望保持与2.4版的向后兼容性 Python2.5支持从未来导入上下文,但Python2.4没有这样的功能。 我想我可以捕获语句引发的任何错误,并手动输入和退出2.4的上下文,但似乎无法捕获引发的SyntaxerError 是否有任何方法可以完成这项任务,而不是显式检查解释器版本? 下面是我要做的事情的要点和我遇到的问题。在现实生活中,我无法控制con

我正在尝试使用python守护进程模块。它提供daemon.DaemonContext类来正确地守护脚本。虽然我主要针对Python2.6+,但我希望保持与2.4版的向后兼容性

Python2.5支持从未来导入上下文,但Python2.4没有这样的功能。 我想我可以捕获语句引发的任何错误,并手动输入和退出2.4的上下文,但似乎无法捕获引发的SyntaxerError

是否有任何方法可以完成这项任务,而不是显式检查解释器版本? 下面是我要做的事情的要点和我遇到的问题。在现实生活中,我无法控制context类,因此它需要在不损坏原始类的情况下工作

如果Python2.4无法运行Python守护进程,则无需担心;我至少希望能够捕捉错误并实现回退或其他方法

谢谢你的帮助

#!/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编译器在编译时进行诊断的——您可能试图从作为同一模块的一部分编译的代码中“捕获”它(例如,这就是您在代码示例中所做的),因此它当然不起作用——您的“捕获”代码尚未编译(因为编译未成功终止)因此它无法捕获任何内容

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

我认为这两种可能性都不适合您的目的。不幸的是,我怀疑使用两个单独的模块(可能根据“Dothis 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 ,快2.6倍,几乎是260倍。一般(很少有例外),干净(即“Python”)。这种方法在Python中会得到更好的优化——通常,至少部分原因可能是Python核心开发人员专注于促进和鼓励使用他们喜欢的结构,而不是他们不喜欢的结构。

我担心这一点。正如您所说,有条件地编译字符串对于没有充分的理由,所以这是不可能的。所以我将在模块之间进行选择,同时使它们尽可能小。至于如何区分,捕获错误和检查版本基本上都是“干净的”那么,每次比较sys.version\u信息或有时吃异常,哪个更快?这可能可以忽略不计,但我想听听你的意见。谢谢你的快速回答!@hippie,对于微基准测试,永远不要猜测,总是测量。
timeit
是你的朋友。编辑我的A以提供一个示例。当然,版本检查更快而不是编译。要使用比较测试进行任何操作,都需要导入(编译)代码,而不仅仅是进行两次赋值。对于Python 2.5,异常检查实际上稍微快一点(在我的机器上,通过timeit进行了1000000次迭代,3.47s对3.87s)。但是,在2.4上,由于每次都捕获SyntaxError,异常检查的速度大约慢了30倍。版本检查显然更好,但您的示例没有显示真正的原因。=)