如何在Python中包装内置方法? (或'如何通过引用传递它们')

时间:2009-11-11 11:54:18

标签: python exception-handling wrapper

我想用一个也应该捕获异常的包装器来包装默认的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解决方法?

3 个答案:

答案 0 :(得分:3)

您的代码存在的问题是,在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)

答案 1 :(得分:2)

尝试添加global open。在一般情况下,您可能需要查看this section of the manual

  

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

     

大多数应用程序通常不会显式访问此模块,但在提供与内置值同名的对象的模块中可能很有用,但在该模块中还需要内置该名称。例如,在一个想要实现包装内置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的替代实现可能不会使用它。

答案 2 :(得分: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