python 的“with”语句是用来做什么的?

2024-11-26 08:36:00
admin
原创
149
摘要:问题描述:今天我第一次遇到了 Pythonwith语句。几个月来我一直在轻度使用 Python,甚至不知道它的存在!鉴于它的地位有些模糊,我认为值得问一问:withPython语句设计用来做 什么?你用它做什么?我需要注意哪些问题,或者使用时有哪些常见的反模式? 有哪些情况try..finally比更好wit...

问题描述:

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

  1. withPython语句设计用来做 什么?

  2. 你用它做什么?

  3. 我需要注意哪些问题,或者使用时有哪些常见的反模式? 有哪些情况try..finally比更好with

  4. 为什么它没有被更广泛地使用?

  5. 哪些标准库类与其兼容?


解决方案 1:

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

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

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.stdin重定向到其他文件句柄,稍后再恢复它们:sys.stdout`sys.stderr`

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"

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

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

解决方案 2:

我推荐两个有趣的讲座:

  • PEP 343 “with” 语句

  • Effbot理解 Python 的“with”语句

1.
语句with用于使用上下文管理器定义的方法包装块的执行。这样可以try...except...finally封装常见的使用模式,方便重复使用。

2.
你可以这样做:

with open("foo.txt") as foo_file:
    data = foo_file.read()

或者

from contextlib import nested
with nested(A(), B(), C()) as (X, Y, Z):
   do_something()

或 (Python 3.1)

with open('data') as input_file, open('result', 'w') as output_file:
   for line in input_file:
     output_file.write(parse(line))

或者

lock = threading.Lock()
with lock:
    # Critical section of code

3.
我在这里没有看到任何反模式。

引用Dive into Python 的话:

尝试..最后很好。用更好。

4.
我猜测这可能和程序员使用try..catch..finally其他语言的语句的习惯有关。

解决方案 3:

Pythonwith语句是 C++ 中常用的语法的内置语言支持Resource Acquisition Is Initialization。它旨在允许安全地获取和释放操作系统资源。

with语句在范围/块内创建资源。您可以使用块内的资源编写代码。当块退出时,无论块中代码的结果如何(即块是正常退出还是由于异常而退出),资源都会被干净地释放。

Python 库中的许多资源都遵循该with语句所需的协议,因此可以开箱即用。但是,任何人都可以通过实施有据可查的协议来创建可以在 with 语句中使用的资源:PEP 0343

当您在应用程序中获取必须明确放弃的资源(例如文件、网络连接、锁等)时,请使用它。

解决方案 4:

反模式的一个例子是,在循环内部使用循环,而使用循环外部with会更有效with

例如

for row in lines:
    with open("outfile","a") as f:
        f.write(row)

对比

with open("outfile","a") as f:
    for row in lines:
        f.write(row)

第一种方式是每次打开和关闭文件,row这可能会导致性能问题,而第二种方式只打开和关闭文件一次。

解决方案 5:

再次,为了完整性,我将添加我最有用的语句用例with

我进行了很多科学计算,对于某些活动,我需要Decimal用于任意精度计算的库。我的代码中有一部分需要高精度,而其他大部分则需要较低的精度。

我将默认精度设置为较低的数字,然后用它with来获得某些部分的更精确的答案:

from decimal import localcontext

with localcontext() as ctx:
    ctx.prec = 42   # Perform a high precision calculation
    s = calculate_something()
s = +s  # Round the final result back to the default precision

我经常在超几何测试中使用它,它需要对大数进行除法,从而得到阶乘。进行基因组规模计算时,必须小心舍入和溢出错误。

解决方案 6:

参见PEP 343 - “with” 语句,最后有一个示例部分。

... 在 Python 语言中加入了新的语句“with”,使得可以分解出 try/finally 语句的标准用法。

解决方案 7:

第 1、2 和 3 点已得到合理涵盖:

4:它相对较新,仅适用于python2.6+(或使用python2.5 from __future__ import with_statement

解决方案 8:

with 语句与所谓的上下文管理器一起工作:

http://docs.python.org/release/2.5.2/lib/typecontextmanager.html

这个想法是通过在离开“with”块后进行必要的清理来简化异常处理。一些 Python 内置函数已经可以作为上下文管理器使用。

解决方案 9:

另一个开箱即用支持的示例,当您习惯于内置行为方式时,一开始可能会有点困惑open(),这些示例是connection流行数据库模块的对象,例如:

  • sqlite3

  • psycopg2

  • CX_Oracle

这些connection对象是上下文管理器,因此可以在中开箱即用with-statement,但是在使用上述内容时请注意:

with-block完成时,无论是否发生异常,连接都不会关闭。如果with-block完成时发生异常,则事务将回滚,否则将提交事务。

这意味着程序员必须小心地自己关闭连接,但允许获取连接并在多个连接中使用它with-statements,如psycopg2 文档中所示:

conn = psycopg2.connect(DSN)

with conn:
    with conn.cursor() as curs:
        curs.execute(SQL1)

with conn:
    with conn.cursor() as curs:
        curs.execute(SQL2)

conn.close()

在上面的例子中,您会注意到 的cursor对象psycopg2也是上下文管理器。从有关该行为的相关文档中:

cursor退出时with-block,它将关闭,并释放最终与其关联的任何资源。事务的状态不受影响。

解决方案 10:

在 python 中,通常使用“ with ”语句来打开文件、处理文件中的数据以及关闭文件而不调用 close() 方法。“ with ”语句通过提供清理活动使异常处理更简单。

with 的一般形式:

with open(“file name”, “mode”) as file_var:
    processing statements

注意:无需通过调用来关闭close()文件file_var.close()

解决方案 11:

这里的答案很棒,但只是添加一个对我有帮助的简单答案:

with open("foo.txt") as file:
    data = file.read()
  • open返回file

  • 自 2.6 版起,python 添加了方法__enter__和。__exit__`file`

  • with就像一个 for 循环,它调用__enter__,运行一次循环,然后调用__exit__

  • with适用于具有__enter__和的任何实例__exit__

文件被锁定,在关闭之前不能被其他进程重新使用,__exit__请关闭它。

来源:http ://web.archive.org/web/20180310054708/http://effbot.org/zone/python-with-statement.htm

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用