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