赞
踩
今天,我第一次碰到了Python with
语句。 我已经使用Python几个月了,甚至都不知道它的存在! 考虑到它的地位有些晦涩,我认为值得一问:
with
语句旨在用于什么? try..finally
比with
? with语句适用于所谓的上下文管理器:
http://docs.python.org/release/2.5.2/lib/typecontextmanager.html
这个想法是通过在离开“ with”块之后进行必要的清理来简化异常处理。 某些python内置插件已经可以用作上下文管理器。
参见PEP 343-'with'语句 ,最后有一个示例部分。
... Python语言的新语句“ with”使排除try / finally语句的标准用法成为可能。
我会建议两个有趣的讲座:
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进入Python :
试试..最终是好的。 与更好。
4.我想这与程序员使用来自其他语言的try..catch..finally
语句的习惯有关。
第1、2和3点被合理地涵盖了:
4:它相对较新,仅适用于python2.6 +(或python2.5使用from __future__ import with_statement
)
我相信这已经被我之前的其他用户回答了,所以我仅出于完整性的目的添加它: with
语句通过将通用的准备工作和清理任务封装在所谓的上下文管理器中来简化异常处理。 可以在PEP 343中找到更多详细信息。 例如, open
语句本身就是一个上下文管理器,它使您可以打开文件,只要在使用它的with
语句的上下文中执行该文件,就可以保持打开状态,并在离开语句后立即将其关闭。上下文,无论您是由于异常还是在常规控制流程中离开了它。 因此, with
语句可以以类似于C ++中的RAII模式的方式使用: with
语句获取某些资源with
并在离开with
上下文时将其释放。
一些示例是:使用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
Python with
语句是C ++中常用的“ Resource Acquisition Is Initialization
惯用语的内置语言支持。 旨在允许安全获取和释放操作系统资源。
with
语句在作用域/块内创建资源。 您可以使用块中的资源编写代码。 当该块退出时,无论该块中代码的结果如何(即该块是正常退出还是由于异常而退出),资源都会被干净地释放。
Python库中的许多资源都遵循with
语句所需的协议,因此可以立即使用。 但是,任何人都可以通过实施有据可查的协议来制作可在with语句中使用的资源: PEP 0343
每当您在应用程序中获取必须明确放弃的资源(例如文件,网络连接,锁等)时,都应使用它。
反模式的一个例子可能是使用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
打开和关闭文件,而第二种方法是一次打开和关闭文件,这可能会导致性能问题。
再次为了完整性,我将为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
我在“超几何测试”中经常使用此功能,该测试需要将大量数字除以形式阶乘。 在进行基因组比例计算时,必须注意舍入和溢出错误。
开箱即用支持的另一个示例是流行的数据库模块的connection
对象,当您习惯于内置open()
行为时,乍一看可能会感到困惑。
connection
对象是上下文管理器,因此可以在with-statement
中直接使用,但是在使用上述说明时,请注意:
with-block
完成后,无论有无异常, 连接都不会关闭 。 如果with-block
异常结束,则事务将回滚,否则将提交事务。
这意味着程序员必须注意自己关闭连接,但允许获取连接,并在多个with-statements
使用它,如psycopg2 docs中所示:
- 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()
在上面的示例中,您会注意到psycopg2
的cursor
对象也是上下文管理器。 从有关行为的相关文档中:
当
cursor
退出with-block
它会关闭,释放最终与之关联的任何资源。 交易状态不受影响。
在python中,通常使用“ with ”语句来打开文件,处理文件中存在的数据,以及不调用close()方法而关闭文件。 “ with”语句通过提供清理活动使异常处理更加简单。
的一般形式:
- with open(“file name”, “mode”) as file-var:
- processing statements
注意:无需通过在file-var.close()上调用close()来关闭文件
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。