通过语句和上下文管理器了解 Python
我试图理解 with
语句。我知道它应该替换 try
/except
块。
现在假设我做了这样的事情:
try:
name = "rubicon" / 2 # to raise an exception
except Exception as e:
print("No, not possible.")
finally:
print("OK, I caught you.")
如何用上下文管理器替换它?
I am trying to understand the with
statement. I understand that it is supposed to replace the try
/except
block.
Now suppose I do something like this:
try:
name = "rubicon" / 2 # to raise an exception
except Exception as e:
print("No, not possible.")
finally:
print("OK, I caught you.")
How do I replace this with a context manager?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
contextlib.contextmanager 函数装饰器提供一种提供上下文管理器的便捷方法,无需编写您自己的成熟的 ContextManager 类(使用 __enter__ 和 __exit__ 方法,因此您不必记住
__exit__
方法的参数,或者__exit__
方法必须返回 True
才能抑制异常)。相反,您可以在希望with
块运行时编写一个具有单个yield
的函数,并捕获任何异常(实际上来自yield
)像平常一样。为什么要费尽心思去编写上下文管理器呢?代码重用。您可以在多个位置使用相同的上下文管理器,而不必重复异常处理。如果异常处理对于该情况是唯一的,那么就不必使用上下文管理器。但是,如果相同的模式一次又一次出现(或者如果它可能对您的用户而言,例如关闭文件、解锁互斥体),那么额外的麻烦是值得的。如果异常处理有点复杂,这也是一种简洁的模式,因为它将异常处理与代码流的主线分开。
The contextlib.contextmanager function decorator provides a handy way of providing a context manager without the need to write a full-fledged
ContextManager
class of your own (with__enter__
and__exit__
methods, so you don't have to remember the arguments to the__exit__
method, or that the__exit__
method mustreturn True
in order to suppress the exception). Instead, you write a function with a singleyield
at the point you want thewith
block to run, and you trap any exceptions (that effectively come from theyield
) as you normally would.Why go to the extra trouble of writing a context manager? Code re-use. You can use the same context manager in multiple places, without having to duplicate the exception handling. If the exception handling is unique to that situation, then don't bother with a context manager. But if the same pattern crops up again and again (or if it might for your users, e.g., closing a file, unlocking a mutex), it's worth the extra trouble. It's also a neat pattern to use if the exception handling is a bit complicated, as it separates the exception handling from the main line of code flow.
with
并没有真正取代try
/except
,而是try
/finally.不过,您可以让上下文管理器在异常情况下执行与非异常情况不同的操作:
返回 True
部分是上下文管理器决定抑制异常的地方(如您可以通过不在except
子句中重新引发它来实现)。with
doesn't really replacetry
/except
, but, rather,try
/finally
. Still, you can make a context manager do something different in exception cases from non-exception ones:The
return True
part is where the context manager decides to suppress the exception (as you do by not re-raising it in yourexcept
clause).Python 中的
with
旨在包装一组应在其中设置、销毁或关闭资源的语句。在这方面,它与 try...finally 类似,因为即使在异常之后,finally 子句也会被执行。上下文管理器是一个实现两个方法的对象:
__enter__
和__exit__
。它们分别在with
块之前和之后调用。例如,看一下经典的
open()
示例:Open 返回一个
File
对象,该对象或多或少类似于实现
和__enter__
像self.close()
一样返回self__exit__
。The
with
in Python is intended for wrapping a set of statements where you should set up and destroy or close resources. It is in a way similar totry...finally
in that regard as the finally clause will be executed even after an exception.A context manager is an object that implements two methods:
__enter__
and__exit__
. Those are called immediately before and after (respectively) thewith
block.For instance, take a look at the classic
open()
example:Open returns a
File
object that implements__enter__
more or less likereturn self
and__exit__
likeself.close()
.上下文管理器的组件
示例
我将举一个简单的示例来向您展示为什么我们需要上下文管理器。中国新疆的冬天,开门后应立即关门。如果你忘记关上它,你会着凉的。
在家取东西时,应该打开门,取东西,然后关上门。
输出是:
解释
当你启动一个 Door 类时,它将调用 __init__ 方法,该方法将打印
“当你不在家时,门被关上了”和 __enter__ 方法将打印“我已经打开了门”并返回一个名为 dr. 的门实例。当在 with 块中调用 self.fetchsomethings 时,该方法将打印“我已经获取了一些东西”。当块完成时。上下文管理器将调用 __exit__
方法,它会打印“pong!门已关闭”。当你不使用 with
关键字 ,__enter__ 和 __exit__ 将不会被调用!!!!
The Components of Context Manager
Example
I will give a simple example to show you why we need a context manager. During the winter of Xinjiang, China, you should close a door immediately when you open a door. if you forget to close it, you will get cold.
when fetch things at home, you should open a door, fetch somethings and close the door.
the output is:
Explanation
when you initiate a Door class, it will call __init__ method that will print
"the door was closed when you are not in home" and __enter__ method that will print "I have opened the door" and return a door instance called dr. when call self.fetchsomethings in with block, the method will print "I have fetched somethings".when the block is finished.the context manager will invoke __exit__
method and it will print "pong!the door has closed" .when you do not use with
keyword ,__enter__and __exit__ will not be invoked!!!!
with
语句或上下文管理器可以帮助处理资源(尽管可能用途更多)。假设您打开了一个文件进行写入:
您现在有一个打开的文件句柄。在处理文件期间,没有其他程序可以写入它。为了让其他程序写入它,您必须关闭文件句柄:
但是,在关闭文件之前发生了错误:
现在将发生的是该函数或整个程序将退出,同时使您的文件保持打开的句柄。 (CPython 在终止时清理句柄,并且句柄与程序一起释放,但您不应该指望这一点)
with 语句确保一旦您离开缩进,它将关闭文件句柄:
with
语句可以用于更多事情。例如:threading.Lock()
几乎所有使用上下文管理器完成的事情都可以通过
try: ... finally: ...
来完成但上下文管理器更好用、更舒适、更具可读性,并且通过实现 __enter__ 和 __exit__ 提供了一个易于使用的界面。创建上下文管理器是通过实现
__enter__()
来完成的 和__exit__()
在普通课堂上。__enter__()
告诉当上下文管理器启动时要做什么,以及__exit__()
当上下文管理器存在时要做什么(给__exit__()
提供异常> 方法(如果发生异常)创建上下文管理器的快捷方式可以在 中找到上下文库。它将生成器包装为上下文管理器。
with
statements or context managers are there to aid with resources (although may be used for much more).Let's say you opened a file for writing:
You now have an open file handle. During the handling of your file, no other program can write to it. In order to let other programs write to it, you must close the file handle:
But, before closing your file an error occured:
What will happen now is that the function or entire program will exit, while leaving your file with an open handle. (CPython cleans handles on termination and handles are freed together with a program but you shouldn't count on that)
A with statement ensures that as soon as you leave it's indentation, it will close the file handle:
with
statements may be used for many more things. For example:threading.Lock()
Almost everything done with a context manager can be done with
try: ... finally: ...
but context managers are nicer to use, more comfortable, more readable and by implementing__enter__
and__exit__
provide an easy to use interface.Creating context managers is done by implementing
__enter__()
and__exit__()
in a normal class.__enter__()
tells what to do when a context manager starts and__exit__()
when a context manager exists (giving the exception to the__exit__()
method if an exception occurred)A shortcut for creating context managers can be found in contextlib. It wraps a generator as a context manager.
管理资源:在任何编程语言中,文件操作或数据库连接等资源的使用都很常见。但这些资源的供应是有限的。因此,主要问题在于如何确保这些资源在使用后得到释放。如果不释放它们,则会导致资源泄漏,并可能导致系统变慢或崩溃。如果用户有一个自动设置和拆除资源的机制,那将会非常有帮助。在Python中,它可以通过使用上下文管理器来实现,上下文管理器有助于正确处理资源。执行文件操作的最常见方法是使用如下所示的关键字:
打开文件时,会消耗文件描述符,这是一种有限的资源。一个进程一次只能打开一定数量的文件。下面的程序演示了这一点。
它导致错误:
OSError: [Errno 24] Too much open files: 'test.txt'
Python 提供了一种简单的方法来管理资源:上下文管理器。使用 with 关键字。当它被评估时,它应该产生一个执行上下文管理的对象。上下文管理器可以使用类或函数(带有装饰器)来编写。
创建上下文管理器:当使用类创建上下文管理器时,用户需要确保该类具有方法:
__enter__()
和__exit__()
。__enter__()
返回需要管理的资源,__exit__()
不返回任何内容,但执行清理操作。首先,让我们创建一个名为 ContextManager 的简单类,以了解使用类创建上下文管理器的基本结构,如下所示:在本例中,创建了一个 ContextManager 对象。这被分配给关键字 ie manager 之后的变量。运行上述程序时,将按顺序执行以下内容:
__init__()
__enter__()
__exit__()[该方法中的参数用于管理异常]
Managing Resources: In any programming language, the usage of resources like file operations or database connections is very common. But these resources are limited in supply. Therefore, the main problem lies in making sure to release these resources after usage. If they are not released then it will lead to resource leakage and may cause the system to either slow down or crash. It would be very helpful if users have a mechanism for the automatic setup and teardown of resources. In Python, it can be achieved by the usage of context managers which facilitate the proper handling of resources. The most common way of performing file operations is by using the keyword as shown below:
When a file is opened, a file descriptor is consumed which is a limited resource. Only a certain number of files can be opened by a process at a time. The following program demonstrates it.
it lead the error:
OSError: [Errno 24] Too many open files: 'test.txt'
Python provides an easy way to manage resources: Context Managers. The with keyword is used. When it gets evaluated it should result in an object that performs context management. Context managers can be written using classes or functions(with decorators).
Creating a Context Manager: When creating context managers using classes, user need to ensure that the class has the methods:
__enter__()
and__exit__()
. The__enter__()
returns the resource that needs to be managed and the__exit__()
does not return anything but performs the cleanup operations. First, let us create a simple class called ContextManager to understand the basic structure of creating context managers using classes, as shown below:In this case, a ContextManager object is created. This is assigned to the variable after the keyword i.e manager. On running the above program, the following get executed in sequence:
__init__()
__enter__()
__exit__()
[the parameters in this method are used to manage exceptions]