什么是蟒蛇“与"?声明专为? [英] What is the python "with" statement designed for?

查看:50
本文介绍了什么是蟒蛇“与"?声明专为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我今天第一次遇到 Python with 语句.几个月来我一直在轻松使用 Python,甚至不知道它的存在!鉴于它的地位有些模糊,我认为值得一问:

I came across the Python with statement for the first time today. I've been using Python lightly for several months and didn't even know of its existence! Given its somewhat obscure status, I thought it would be worth asking:

  1. 什么是 Python with 语句设计用于?
  2. 做什么你用它吗?
  3. 有吗我需要注意的问题,或者与相关的常见反模式它的用途?在任何情况下使用 try..finally 比使用 with 更好?
  4. 为什么没有更广泛地使用它?
  5. 哪些标准库类与其兼容?
  1. What is the Python with statement designed to be used for?
  2. What do you use it for?
  3. Are there any gotchas I need to be aware of, or common anti-patterns associated with its use? Any cases where it is better use try..finally than with?
  4. Why isn't it used more widely?
  5. Which standard library classes are compatible with it?

推荐答案

  1. 我相信在我之前的其他用户已经回答了这个问题,所以我只是为了完整性才添加它:with 语句通过封装常见的准备和清理任务来简化异常处理在所谓的上下文管理器中.更多细节可以在 PEP 343 中找到.例如,open 语句本身就是一个上下文管理器,它允许您打开一个文件,只要执行在 with 语句的上下文中,它就保持打开状态使用它的地方,并在离开上下文时立即关闭它,无论您是因为异常还是在常规控制流期间离开它.with 语句因此可以以类似于 RAII 模式的方式使用在 C++ 中:某些资源由 with 语句获取,并在您离开 with 上下文时释放.

  1. I believe this has already been answered by other users before me, so I only add it for the sake of completeness: the with statement simplifies exception handling by encapsulating common preparation and cleanup tasks in so-called context managers. More details can be found in PEP 343. For instance, the open statement is a context manager in itself, which lets you open a file, keep it open as long as the execution is in the context of the with statement where you used it, and close it as soon as you leave the context, no matter whether you have left it because of an exception or during regular control flow. The with statement can thus be used in ways similar to the RAII pattern in C++: some resource is acquired by the with statement and released when you leave the with context.

一些例子是:使用 with open(filename) as fp: 打开文件,使用 with lock: 获取锁(其中 lockthreading.Lock 的一个实例).您还可以使用 contextlib 中的 contextmanager 装饰器构建自己的上下文管理器.例如,当我必须临时更改当前目录然后返回到我所在的位置时,我经常使用它:

Some examples are: opening files using with open(filename) as fp:, acquiring locks using with lock: (where lock is an instance of threading.Lock). You can also construct your own context managers using the contextmanager decorator from contextlib. For instance, I often use this when I have to change the current directory temporarily and then return to where I was:

from contextlib import contextmanager
import os

@contextmanager
def working_directory(path):
    current_dir = os.getcwd()
    os.chdir(path)
    try:
        yield
    finally:
        os.chdir(current_dir)

with working_directory("data/stuff"):
    # do something within data/stuff
# here I am back again in the original working directory

这是另一个示例,它临时将 sys.stdinsys.stdoutsys.stderr 重定向到某个其他文件句柄并稍后恢复它们:

Here's another example that temporarily redirects sys.stdin, sys.stdout and sys.stderr to some other file handle and restores them later:

from contextlib import contextmanager
import sys

@contextmanager
def redirected(**kwds):
    stream_names = ["stdin", "stdout", "stderr"]
    old_streams = {}
    try:
        for sname in stream_names:
            stream = kwds.get(sname, None)
            if stream is not None and stream != getattr(sys, sname):
                old_streams[sname] = getattr(sys, sname)
                setattr(sys, sname, stream)
        yield
    finally:
        for sname, stream in old_streams.iteritems():
            setattr(sys, sname, stream)

with redirected(stdout=open("/tmp/log.txt", "w")):
     # these print statements will go to /tmp/log.txt
     print "Test entry 1"
     print "Test entry 2"
# back to the normal stdout
print "Back to normal stdout again"

最后,另一个创建临时文件夹并在离开上下文时清理它的示例:

And finally, another example that creates a temporary folder and cleans it up when leaving the context:

from tempfile import mkdtemp
from shutil import rmtree

@contextmanager
def temporary_dir(*args, **kwds):
    name = mkdtemp(*args, **kwds)
    try:
        yield name
    finally:
        shutil.rmtree(name)

with temporary_dir() as dirname:
    # do whatever you want

这篇关于什么是蟒蛇“与"?声明专为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆