context manager
来源:互联网 发布:用友nc系统java插件 编辑:程序博客网 时间:2024/06/05 08:54
1) The "with" statement
with expr [as VAR]:
WITH-BLOCK
"with" statement is something like "RAII" in C++, when "with" statement finishes, all resources will be cleaned automatically even there is exception raised.
For e.g.with open("c:/test.txt") as f: # note this "f" is not returned by open() function, it is actually returned by f.__enter__() function
for line in f:
print line
# "f" is closed automatically
2) Under the hood:
- The expression is evaluated and should result in an object called a “context manager”. The context manager must have __enter__() and __exit__() methods.
- The context manager’s __enter__() method is called. The value returned from __enter__() is assigned to VAR. If no 'as VAR' clause is present, the value is simply discarded.
- The code in WITH-BLOCK is executed.
- If WITH-BLOCK raises an exception, the __exit__(type, value, traceback) is called with the exception details, the same values returned by sys.exc_info(). The __exit__() method’s return value controls whether the exception is re-raised:any false value re-raises the exception, and True will result in suppressing it. You’ll only rarely want to suppress the exception, because if you do the author of the code containing the ‘with‘ statement will never realize anything went wrong.
- If WITH-BLOCK didn’t raise an exception, the __exit__() method is still called, but type, value, and traceback are all None.
3) Writing Context Manager (example)
class DatabaseConnection:
# Database interface
def cursor (self):
"Returns a cursor object and starts a new transaction"
def commit (self):
"Commits current transaction"
def rollback (self):
"Rolls back current transaction"
def __enter__ (self):
# Code to start a new transaction
cursor = self.cursor()
return cursor
def __exit__ (self, type, value, tb): # when reaching the end of this func, "None" is returned implicitly.
if tb is None:
# No exception, so commit
self.commit()
else:
# Exception occurred, so rollback.
self.rollback()
# return False
# Usage:
db_connection = DatabaseConnection()
with db_connection as cursor:
cursor.execute('insert into ...')
cursor.execute('delete from ...')
# ... more operations ...
4) The "contextlib" module
The "contextlib" module provides some functions and a decorator that are useful for writing objects for use with the ‘with‘ statement. The decorator is called contextmanager(), and lets you write a single generator function instead of defining a new class.The generator should yield exactly one value.The code up to the yield will be executed as the __enter__() method, and the value yielded will be the method’s return value that will get bound to the variable in the ‘with‘ statement’s as clause, if any.The code after the yield will be executed in the __exit__() method. Any exception raised in the block will be raised by the yield statement.
Example:
class DatabaseConnection:
# Database interface
def cursor (self):
"Returns a cursor object and starts a new transaction"
def commit (self):
"Commits current transaction"
def rollback (self):
"Rolls back current transaction"
def __enter__ (self):
# Code to start a new transaction
cursor = self.cursor()
return cursor
def __exit__ (self, type, value, tb): # when reaching the end of this func, "None" is returned implicitly.
if tb is None:
# No exception, so commit
self.commit()
else:
# Exception occurred, so rollback.
self.rollback()
# return False
# Usage:
db_connection = DatabaseConnection()
with db_connection as cursor:
cursor.execute('insert into ...')
cursor.execute('delete from ...')
# ... more operations ...
4) The "contextlib" module
The "contextlib" module provides some functions and a decorator that are useful for writing objects for use with the ‘with‘ statement. The decorator is called contextmanager(), and lets you write a single generator function instead of defining a new class.The generator should yield exactly one value.The code up to the yield will be executed as the __enter__() method, and the value yielded will be the method’s return value that will get bound to the variable in the ‘with‘ statement’s as clause, if any.The code after the yield will be executed in the __exit__() method. Any exception raised in the block will be raised by the yield statement.
Example:
[Rewrite the example above by using contextlib]
from contextlib import contextmanager
@contextmanager
def db_transaction (connection):
cursor = connection.cursor()
try:
yield cursor
except:
connection.rollback()
raise
else:
connection.commit()
# Usage:
db = DatabaseConnection()
with db_transaction(db) as cursor:
...
5) "contextlib.nested(mgr1, mgr2, ...)"
It combines a number of context managers so you don’t need to write nested ‘with‘ statements.
In this example, the single ‘with‘ statement both starts a database transaction and acquires a thread lock:
lock = threading.Lock()
with nested (db_transaction(db), lock) as (cursor, locked):
...
6) "contextlib.closing(object)"
function returns object so that it can be bound to a variable, and calls object.close() at the end of the block.
Example:
import urllib, sys
from contextlib import closing
with closing(urllib.urlopen('http://www.yahoo.com')) as f:
for line in f:
sys.stdout.write(line)
from contextlib import contextmanager
@contextmanager
def db_transaction (connection):
cursor = connection.cursor()
try:
yield cursor
except:
connection.rollback()
raise
else:
connection.commit()
# Usage:
db = DatabaseConnection()
with db_transaction(db) as cursor:
...
5) "contextlib.nested(mgr1, mgr2, ...)"
It combines a number of context managers so you don’t need to write nested ‘with‘ statements.
In this example, the single ‘with‘ statement both starts a database transaction and acquires a thread lock:
lock = threading.Lock()
with nested (db_transaction(db), lock) as (cursor, locked):
...
6) "contextlib.closing(object)"
function returns object so that it can be bound to a variable, and calls object.close() at the end of the block.
Example:
import urllib, sys
from contextlib import closing
with closing(urllib.urlopen('http://www.yahoo.com')) as f:
for line in f:
sys.stdout.write(line)
0 0
- context manager
- Intent&Context&Manager&Listener
- Python Context Manager
- 关于 context manager
- Python上下文管理器Context Manager
- python: 上下文管理器(context manager)
- Python学习8:上下文管理器(context manager)
- 十六、Python 上下文管理 Context Manager
- Python With语句 和context manager
- Python with语句及context manager
- Python Study(02)之 Context Manager
- Python上下文管理器(context manager)一例
- Python map, lambda, with, context manager学习实践
- Cannot invoke Tomcat manager: FAIL - Context is defined in server.
- Python学习笔记(五)-- 上下文管理器(Context Manager)
- python特性(十三):context manager的__enter__方法
- Python特性(十四):context manager的__exit__方法
- Python特性(十六):由生成器诱导的context manager
- 不错的JQuery屏幕居中提示信息封装,使用方便,可集成到项目
- vector的用法
- Android NDK Overview ---- Android 4.4
- Linux批量替换多文件中的字符串
- Oracle 分区技术
- context manager
- How to create a Oracle 11g RAC Database manually without DBCA ?
- TEMP_FAILURE_RETRY宏的用法
- Android NDK Development ---- Android 4.4
- MySQL日期时间函数大全
- php echo输出中文,读取MYSQL数据 echo 输出中文乱码
- UIScrollview
- ie6 iframe onload window.open
- Android监听WebView滑动到底部