python 上下文管理器_深入了解python上下文管理器

python 上下文管理器

Manage your resources like a pro

像专业人士一样管理您的资源

Python is a particularly clean and sugary language, thanks to its many convenience features. In this post, I will go into context managers in Python, how to use them, where to find them, and how to write your own ones.

由于Python具有许多便利功能,因此它是一种特别干净且含糖的语言。 在本文中,我将介绍Python中的上下文管理器,如何使用它们,在哪里找到它们以及如何编写自己的上下文管理器。

为什么我们需要上下文管理器? (Why do we need Context Managers?)

Context managers are most often used when we are talking about resources. For example, reading/writing from files. Examine this simple snippet:

当我们谈论资源时,最常使用上下文管理器。 例如,从文件读取/写入。 检查以下简单代码段:

f = open('log.txt', 'w') 
f.write('hello world')
f.close()

All this code does is open the log.txt for writing and writes hello world in it. Simple enough. But suppose for a minute, that the code on line 2 throws an exception for no reason whatsoever. In this case, file is still opened, but never closed, as the interpreter never gets to line 3. This is not a problem with a throwaway script, but can become a headache if you are to develop anything serious on Python.

这些代码log.txt就是打开log.txt进行写入,并在其中写入hello world 。 很简单。 但是,请稍等一下,第2行的代码无缘无故地引发了异常。 在这种情况下,文件仍处于打开状态,但从未关闭,这是因为解释器永远不会进入第3行。这不是一次性脚本的问题,但是如果您要在Python上开发任何严肃的东西,可能会变得头疼。

How can we fix this? The try/ finally construction comes into mind:

我们该如何解决? try / finally构造想到了:

f = open('log.txt', 'w') 
try:
f.write('hello world')
finally:
f.close()

This works, since finally will be executed even if an exception is thrown and file descriptor will be discarded. However, this does not look very Pythonish...

这是可行的,因为即使抛出异常并且文件描述符也将被丢弃, finally仍将执行。 但是,这看起来不太像Python。

This is where the with keyword comes into play. It was developed for this specific purpose: to make resource management readable. This snippet is functionally equal to the example above:

这是with关键字起作用的地方。 它是出于以下特定目的而开发的:使资源管理可读。 该代码段在功能上与上面的示例相同:

with open('log.txt', 'w') as f: 
f.write('hello world')

Looks much cleaner, won’t you agree?

看起来更干净,您不同意吗?

上下文管理器如何工作? (How do Context Managers work?)

The logic behind context managers is actually pretty easy. Let’s explore it by writing our own context manager. For an object to be recognized as a context manager, it must implement 2 methods: __enter__ and __exit__:

上下文管理器背后的逻辑实际上很容易。 让我们通过编写我们自己的上下文管理器来探索它。 为了将一个对象识别为上下文管理器,它必须实现2个方法: __enter____exit__

class TestContextManager:
    def __enter__(self):
        print('Entered into context manager!')


    def __exit__(self, *args):
        print('Exiting context manager!')




with TestContextManager():
    print('Inside context manager!')

If you try running this example, you will get the following output:

如果尝试运行此示例,将获得以下输出:

Entered into context manager! 
Inside context manager!
Exiting context manager!

Now let’s try throwing an exception inside with:

现在,让我们尝试在with抛出一个异常:

with TestContextManager(): 
raise Exception()

If you try running this version, note that the __exit__ method is still called, much like the finally clause in the try block. This can be used to clean up and release any resources used by this context manager.

如果尝试运行此版本,请注意,仍会调用__exit__方法,就像try块中的finally子句一样。 这可用于清理和释放此上下文管理器使用的任何资源。

contextlib模块 (contextlib module)

All of this would not be particularly useful if not for the contextlib module. This module is part of the standard library and provides some common constructs to make your life easier.

如果不是contextlib模块,所有这些都不会特别有用。 该模块是标准库的一部分,并提供了一些常用的结构来简化您的生活。

Most notable addition is the @contextmanager decorator. It lets you convert any generator function into a context manager with no additional code at all! Here is an example:

最值得注意的是@contextmanager 装饰器 。 它使您可以将任何生成器函数转换为上下文管理器,而无需任何其他代码! 这是一个例子:

from contextlib import contextmanager




@contextmanager
def get_log_file():
    f = open('log.txt', 'w')
    try:
        yield f
    finally:
        f.close()




with get_log_file() as f:
    f.write('hello world')

While this still requires the use of try/ finally, this lets you abstract this away once and forget about it, while also keeping your code compatible with the rest of the codebase which might not understand context managers as well as you now do.

尽管这仍然需要使用try / finally ,但这使您可以将其抽象一次而不必去理会,同时还可以使代码与可能不如现在理解上下文管理器的其余代码库兼容。

Another useful feature of contextlib is the AbstractContextManager class (new in Python 3.6). This is an Abstract Base Class which implements the __enter__ and __exit__ functions. Use it in your custom context managers to make sure the types are compatible.

contextlib另一个有用功能是AbstractContextManager类(Python 3.6中的新增功能)。 这是一个实现__enter____exit__函数的抽象基类 。 在自定义上下文管理器中使用它以确保类型兼容。

结束语 (Closing notes)

Thank you for reading, I hope you enjoyed this article. In my next post, I will talk about Asynchronous Context Managers. Stay tuned!

感谢您的阅读,希望您喜欢这篇文章。 在下一篇文章中,我将讨论异步上下文管理器。 敬请关注!

资源资源 (Resources)

翻译自: https://levelup.gitconnected.com/python-context-managers-in-depth-52dd2dd2624b

python 上下文管理器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值