use*_*997 16 python contextmanager
我是新手,我只是想了解这个with陈述.我明白它应该替换try/ exceptblock.
现在假设我做了这样的事情:
try:
name='rubicon'/2 # to raise an exception
except Exception as e:
print "no not possible"
finally:
print "Ok I caught you"
Run Code Online (Sandbox Code Playgroud)
如何用上下文管理器替换它?
Ale*_*lli 24
with并没有真正取代try/ except,而是try/ finally.不过,您可以让上下文管理器在异常情况下执行不同的操作:
class Mgr(object):
def __enter__(self): pass
def __exit__(self, ext, exv, trb):
if ext is not None: print "no not possible"
print "OK I caught you"
return True
with Mgr():
name='rubicon'/2 #to raise an exception
Run Code Online (Sandbox Code Playgroud)
该return True部分是上下文管理器决定禁止异常的部分(正如您在except子句中不重新提升它一样).
Pau*_*ice 18
该contextlib.contextmanager功能装饰提供了提供上下文管理器,而不需要写一个全面的一种方便的方法ContextManager类你自己的(与__enter__和__exit__方法,所以你不必记住参数的__exit__方法,或者说,__exit__方法必须return True以抑制异常).相反,您yield在要with运行块的位置编写一个带有单个函数的函数,并且yield像往常一样捕获任何异常(实际上来自).
from contextlib import contextmanager
@contextmanager
def handler():
# Put here what would ordinarily go in the `__enter__` method
# In this case, there's nothing to do
try:
yield # You can return something if you want, that gets picked up in the 'as'
except Exception as e:
print "no not possible"
finally:
print "Ok I caught you"
with handler():
name='rubicon'/2 #to raise an exception
Run Code Online (Sandbox Code Playgroud)
为什么要编写上下文管理器的额外麻烦?代码重用.您可以在多个位置使用相同的上下文管理器,而无需复制异常处理.如果异常处理对于那种情况是唯一的,那么不要打扰上下文管理器.但是,如果相同的模式一次又一次地出现(或者如果它可能对您的用户而言,例如,关闭文件,解锁互斥锁),则值得额外麻烦.如果异常处理有点复杂,它也是一种简洁的模式,因为它将异常处理与代码流的主线分开.
Pab*_*ich 14
将with在Python是用于包裹一组语句,你应该建立和摧毁或关闭的资源.它的方式与此类似try...finally,因为即使在异常之后也会执行finally子句.
上下文管理器是一个实现两种方法的对象:__enter__和__exit__.在with块之前和之后立即调用它们.
例如,看一下经典的open()例子:
with open('temp.txt', 'w') as f:
f.write("Hi!")
Run Code Online (Sandbox Code Playgroud)
开返回一个File实现对象__enter__或多或少像return self和__exit__喜欢self.close().
我将举一个简单的示例向您展示为什么我们需要上下文管理器。在中国新疆的冬天,开门时应立即关闭门。如果忘记关闭它,则会感冒。
class Door:
def __init__(self):
self.doorstatus='the door was closed when you are not at home'
print(self.doorstatus)
def __enter__(self):
print('I have opened the door')
return self
def __exit__(self,*args):
print('pong!the door has closed')
def fetchsomethings(self):
print('I have fetched somethings')
Run Code Online (Sandbox Code Playgroud)
在家里取东西时,应该打开一扇门,取东西然后关上门。
with Door() as dr:
dr.fetchsomethings()
Run Code Online (Sandbox Code Playgroud)
输出为:
the door was closed when you are not at home
I have opened the door
I have fetched somethings
pong!the door has closed
Run Code Online (Sandbox Code Playgroud)
当您启动Door类时,它将调用__init__方法,该方法将显示“您不在家时门已关闭”,而__enter__方法将显示“我已经打开门”,并返回一个名为dr的门实例。当在块中调用self.fetchsomethings时,该方法将显示“我已获取了东西”。当该块完成时,上下文管理器将调用__exit__ 方法,并且将显示“ pong!门已关闭”。与关键字__enter__和__exit__一起使用将不会被调用!!!!
with 语句或上下文管理器可以帮助您获得资源(尽管可能会使用更多资源)。
假设您打开了一个文件进行写入:
f = open(path, "w")
Run Code Online (Sandbox Code Playgroud)
您现在有了一个打开的文件句柄。在处理文件期间,没有其他程序可以写入该文件。为了让其他程序对其进行写入,必须关闭文件句柄:
f.close()
Run Code Online (Sandbox Code Playgroud)
但是,在关闭文件之前发生了错误:
f = open(path, "w")
data = 3/0 # Tried dividing by zero. Raised ZeroDivisionError
f.write(data)
f.close()
Run Code Online (Sandbox Code Playgroud)
现在将发生的是该函数或整个程序将退出,同时使文件保持打开状态。(CPython会在终止时清除句柄,并且将句柄与程序一起释放,但您不应指望该句柄)
with语句可确保您在缩进后立即关闭文件句柄:
with open(path, "w") as f:
data = 3/0 # Tried dividing by zero. Raised ZeroDivisionError
f.write(data)
# In here the file is already closed automatically, no matter what happened.
Run Code Online (Sandbox Code Playgroud)
with语句可以用于更多的事情。例如:threading.Lock()
lock = threading.Lock()
with lock: # Lock is acquired
do stuff...
# Lock is automatically released.
Run Code Online (Sandbox Code Playgroud)
用上下文管理器完成的几乎所有操作都可以完成,try: ... finally: ...但是上下文管理器更易于使用,更舒适,更具可读性,并且可以实现__enter__并__exit__提供易于使用的界面。
创建上下文管理器是通过在常规类中实现__enter__()并完成的__exit__()。
__enter__()告诉上下文管理器启动时和__exit__()上下文管理器存在时的操作(__exit__()如果发生异常,则将异常提供给方法)
在contextlib中可以找到创建上下文管理器的快捷方式。它将生成器包装为上下文管理器。