3

我想用一个也应该捕获异常的包装器来包装默认的 open 方法。这是一个有效的测试示例:

truemethod = open
def fn(*args, **kwargs):
    try:
        return truemethod(*args, **kwargs)
    except (IOError, OSError):
        sys.exit('Can\'t open \'{0}\'. Error #{1[0]}: {1[1]}'.format(args[0], sys.exc_info()[1].args))

open = fn

我想做一个通用的方法:

def wrap(method, exceptions = (OSError, IOError)):
    truemethod = method
    def fn(*args, **kwargs):
        try:
            return truemethod(*args, **kwargs)
        except exceptions:
            sys.exit('Can\'t open \'{0}\'. Error #{1[0]}: {1[1]}'.format(args[0], sys.exc_info()[1].args))

    method = fn

但它不起作用:

>>> wrap(open)
>>> open
<built-in function open>

显然,method是参数的副本,而不是我预期的引用。任何pythonic解决方法?

4

3 回答 3

4

您的代码的问题在于,在内部wrap,您的method = fn语句只是更改 的本地值method,而不是更改 的较大值open。您必须自己分配这些名称:

def wrap(method, exceptions = (OSError, IOError)):
    def fn(*args, **kwargs):
        try:
            return method(*args, **kwargs)
        except exceptions:
            sys.exit('Can\'t open \'{0}\'. Error #{1[0]}: {1[1]}'.format(args[0], sys.exc_info()[1].args))

    return fn

open = wrap(open)
foo = wrap(foo)
于 2009-11-11T12:05:04.583 回答
2

尝试添加global open. 在一般情况下,您可能需要查看手册的这一部分

该模块提供对 Python 的所有“内置”标识符的直接访问;例如,__builtin__.open是内置函数open()的全名。请参阅内置对象一章。

大多数应用程序通常不会显式访问此模块,但在提供与内置值同名的对象的模块中很有用,但其中也需要该名称的内置。例如,在一个模块中想要实现一个包装了内置 open() 的 open() 函数,可以直接使用这个模块:

import __builtin__

def open(path):
    f = __builtin__.open(path, 'r')
    return UpperCaser(f)

class UpperCaser:
    '''Wrapper around a file that converts output to upper-case.'''

    def __init__(self, f):
        self._f = f

    def read(self, count=-1):
        return self._f.read(count).upper()

    # ...

CPython 实现细节:大多数模块的名称__builtins__(注意“s”)作为其全局变量的一部分。的值__builtins__通常是这个模块或者这个模块的__dict__属性值。由于这是一个实现细节,因此 Python 的替代实现可能不会使用它。

于 2009-11-11T11:58:07.727 回答
1

您可以在函数return fn末尾添加,wrap然后执行以下操作:

>>> open = wrap(open)
>>> open('bhla')
Traceback (most recent call last):
  File "<pyshell#24>", line 1, in <module>
    open('bhla')
  File "<pyshell#18>", line 7, in fn
    sys.exit('Can\'t open \'{0}\'. Error #{1[0]}: {1[1]}'.format(args[0], sys.exc_info()[1].args))
SystemExit: Can't open 'bhla'. Error #2: No such file or directory
于 2009-11-11T12:04:36.800 回答