- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章详解Python中contextlib上下文管理模块的用法由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
咱们用的os模块,读取文件的时候,其实他是含有__enter__ __exit__ 。 一个是with触发的时候,一个是退出的时候.
1
2
|
with
file
(
'nima,'
r') as f:
print
f.readline()
|
那咱们自己再实现一个标准的可以with的类。 我个人写python的时候,喜欢针对一些需要有关闭逻辑的代码,构造成with的模式 。 。
1
2
3
4
5
6
7
8
9
10
|
#encoding:utf-8
class
echo:
def
__enter__(
self
):
print
'enter'
def
__exit__(
self
,
*
args):
print
'exit'
with echo() as e:
print
'nima'
|
contextlib是个比with优美的东西,也是提供上下文机制的模块,它是通过Generator装饰器实现的,不再是采用__enter__和__exit__。contextlib中的contextmanager作为装饰器来提供一种针对函数级别的上下文管理机制.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
from
contextlib
import
contextmanager
@contextmanager
def
make_context() :
print
'enter'
try
:
yield
{}
except
RuntimeError, err :
print
'error'
, err
finally
:
print
'exit'
with make_context() as value :
print
value
|
我这里再贴下我上次写的redis分布式锁代码中有关于contextlib的用法。其实乍一看,用了with和contextlib麻烦了,但是最少让你的主体代码更加鲜明了.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
from
contextlib
import
contextmanager
from
random
import
random
DEFAULT_EXPIRES
=
15
DEFAULT_RETRIES
=
5
@contextmanager
def
dist_lock(key, client):
key
=
'lock_%s'
%
key
try
:
_acquire_lock(key, client)
yield
finally
:
_release_lock(key, client)
def
_acquire_lock(key, client):
for
i
in
xrange
(
0
, DEFAULT_RETRIES):
get_stored
=
client.get(key)
if
get_stored:
sleep_time
=
(((i
+
1
)
*
random())
+
2
*
*
i)
/
2.5
print
'Sleeipng for %s'
%
(sleep_time)
time.sleep(sleep_time)
else
:
stored
=
client.
set
(key,
1
)
client.expire(key,DEFAULT_EXPIRES)
return
raise
Exception(
'Could not acquire lock for %s'
%
key)
def
_release_lock(key, client):
client.delete(key)
|
Context Manager API 。
一个上下文管理器通过with声明激活, 而且API包含两个方法。__enter__()方法运行执行流进入到with代码块内。他返回一个对象共上下文使用。当执行流离开with块时,__exit__()方法上下文管理器清除任何资源被使用.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class
Context(
object
):
def
__init__(
self
):
print
'__init__()'
def
__enter__(
self
):
print
'__enter__()'
return
self
def
__exit__(
self
, exc_type, exc_val, exc_tb):
print
'__exit__()'
with Context():
print
'Doing work in the context.'
|
打印结果 。
1
2
3
4
|
__init__()
__enter__()
Doing work in the context.
__exit__()
|
执行上下文管理器时会调用__enter__离开时调用__exit__.
__enter__能返回任意对象,联合一个指定名字于with声明.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
class
WithinContext(
object
):
def
__init__(
self
, context):
print
'WithinContext.__init__(%s)'
%
context
def
do_something(
self
):
print
'WithinContext.do_something()'
def
__del__(
self
):
print
'WithinContext.__del__'
class
Context(
object
):
def
__init__(
self
):
print
'__init__()'
def
__enter__(
self
):
print
'__enter__()'
return
WithinContext(
self
)
def
__exit__(
self
, exc_type, exc_val, exc_tb):
print
'__exit__()'
with Context() as c:
c.do_something()
|
打印结果 。
1
2
3
4
5
6
|
__init__()
__enter__()
WithinContext.__init__(<__main__.Context object at 0x7f579d8e4890>)
WithinContext.do_something()
__exit__()
WithinContext.__del__
|
如果上下文管理器能处理异常,__exit__()应该返回一个True值表明这个异常不需要传播,返回False异常会在执行__exit__之后被引起.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class
Context(
object
):
def
__init__(
self
, handle_error):
print
'__init__(%s)'
%
handle_error
self
.handle_error
=
handle_error
def
__enter__(
self
):
print
'__enter__()'
return
self
def
__exit__(
self
, exc_type, exc_val, exc_tb):
print
'__exit__(%s, %s, %s)'
%
(exc_type, exc_val, exc_tb)
return
self
.handle_error
with Context(
True
):
raise
RuntimeError(
'error message handled'
)
print
with Context(
False
):
raise
RuntimeError(
'error message propagated'
)
|
打印结果 。
1
2
3
4
5
6
7
8
9
10
11
|
__init__(True)
__enter__()
__exit__(<type 'exceptions.RuntimeError'>, error message handled, <traceback object at 0x7fdfb32f8b00>)
__init__(False)
__enter__()
__exit__(<type 'exceptions.RuntimeError'>, error message propagated, <traceback object at 0x7fdfb32f8b90>)
Traceback (most recent call last):
File "test.py", line 23, in <module>
raise RuntimeError('error message propagated')
RuntimeError: error message propagated
|
从生成器到上下文管理器 。
创建上下文管理的传统方法,通过编写一个类与__enter__()和__exit__()方法,并不困难。但有时比你需要的开销只是管理一个微不足道的上下文。在这类情况下,您可以使用contextmanager() decorat or 生成器函数转换成一个上下文管理器.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
import
contextlib
@contextlib
.contextmanager
def
make_context():
print
' entering'
try
:
yield
{}
except
RuntimeError, err:
print
' Error:'
, err
finally
:
print
' exiting'
print
'Normal:'
with make_context() as value:
print
' inside with statement:'
, value
print
print
'handled ereor:'
with make_context() as value:
raise
RuntimeError(
'show example of handling an error'
)
print
print
'unhandled error:'
with make_context() as value:
raise
ValueError(
'this exception is not handled'
)
|
打印结果 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
Normal:
entering
inside with statement: {}
exiting
handled ereor:
entering
Error: show example of handling an error
exiting
unhandled error:
entering
exiting
Traceback (most recent call last):
File "test.py", line 30, in <module>
raise ValueError('this exception is not handled')
ValueError: this exception is not handled
|
嵌套上下文 。
使用nested()可以同时管理多个上下文.
1
2
3
4
5
6
7
8
9
10
|
import
contextlib
@contextlib
.contextmanager
def
make_context(name):
print
'entering:'
, name
yield
name
print
'exiting:'
, name
with contextlib.nested(make_context(
'A'
), make_context(
'B'
), make_context(
'C'
)) as (A, B, C):
print
'inside with statement:'
, A, B, C
|
打印结果 。
1
2
3
4
5
6
7
|
entering: A
entering: B
entering: C
inside with statement: A B C
exiting: C
exiting: B
exiting: A
|
因为Python 2.7和以后的版本不赞成使用nested(),因为可以直接嵌套 。
1
2
3
4
5
6
7
8
9
10
|
import
contextlib
@contextlib
.contextmanager
def
make_context(name):
print
'entering:'
, name
yield
name
print
'exiting:'
, name
with make_context(
'A'
) as A, make_context(
'B'
) as B, make_context(
'C'
) as C:
print
'inside with statement:'
, A, B, C
|
关闭open的句柄 。
文件类支持上下文管理器, 但是有一些对象不支持。还有一些类使用close()方法但是不支持上下文管理器。我们使用closing()来为他创建一个上下文管理器。(类必须有close方法) 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
import
contextlib
class
Door(
object
):
def
__init__(
self
):
print
' __init__()'
def
close(
self
):
print
' close()'
print
'Normal Example:'
with contextlib.closing(Door()) as door:
print
' inside with statement'
print
print
'Error handling example:'
try
:
with contextlib.closing(Door()) as door:
print
' raising from inside with statement'
raise
RuntimeError(
'error message'
)
except
Exception, err:
print
' Had an error:'
, err
|
打印结果 。
1
2
3
4
5
6
7
8
9
10
|
Normal Example:
__init__()
inside with statement
close()
Error handling example:
__init__()
raising from inside with statement
close()
Had an error: error message
|
最后此篇关于详解Python中contextlib上下文管理模块的用法的文章就讲到这里了,如果你想了解更多关于详解Python中contextlib上下文管理模块的用法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我最近在我的机器上安装了 cx_Oracle 模块,以便连接到远程 Oracle 数据库服务器。 (我身边没有 Oracle 客户端)。 Python:版本 2.7 x86 Oracle:版本 11.
我想从 python timeit 模块检查打印以下内容需要多少时间,如何打印, import timeit x = [x for x in range(10000)] timeit.timeit("
我盯着 vs 代码编辑器上的 java 脚本编码,当我尝试将外部模块包含到我的项目中时,代码编辑器提出了这样的建议 -->(文件是 CommonJS 模块;它可能会转换为 ES6 模块。 )..有什么
我有一个 Node 应用程序,我想在标准 ES6 模块格式中使用(即 "type": "module" in the package.json ,并始终使用 import 和 export)而不转译为
我正在学习将 BlueprintJS 合并到我的 React 网络应用程序中,并且在加载某些 CSS 模块时遇到了很多麻烦。 我已经安装了 npm install @blueprintjs/core和
我需要重构一堆具有这样的调用的文件 define(['module1','module2','module3' etc...], function(a, b, c etc...) { //bun
我是 Angular 的新手,正在学习各种教程(Codecademy、thinkster.io 等),并且已经看到了声明应用程序容器的两种方法。首先: var app = angular.module
我正在尝试将 OUnit 与 OCaml 一起使用。 单元代码源码(unit.ml)如下: open OUnit let empty_list = [] let list_a = [1;2;3] le
我在 Angular 1.x 应用程序中使用 webpack 和 ES6 模块。在我设置的 webpack.config 中: resolve: { alias: { 'angular':
internal/modules/cjs/loader.js:750 return process.dlopen(module, path.toNamespacedPath(filename));
在本教程中,您将借助示例了解 JavaScript 中的模块。 随着我们的程序变得越来越大,它可能包含许多行代码。您可以使用模块根据功能将代码分隔在单独的文件中,而不是将所有内容都放在一个文件
我想知道是否可以将此代码更改为仅调用 MyModule.RED 而不是 MyModule.COLORS.RED。我尝试将 mod 设置为变量来存储颜色,但似乎不起作用。难道是我方法不对? (funct
我有以下代码。它是一个 JavaScript 模块。 (function() { // Object var Cahootsy; Cahootsy = { hello:
关闭。这个问题是 opinion-based 。它目前不接受答案。 想要改进这个问题?更新问题,以便 editing this post 可以用事实和引文来回答它。 关闭 2 年前。 Improve
从用户的角度来看,一个模块能够通过 require 加载并返回一个 table,模块导出的接口都被定义在此 table 中(此 table 被作为一个 namespace)。所有的标准库都是模块。标
Ruby的模块非常类似类,除了: 模块不可以有实体 模块不可以有子类 模块由module...end定义. 实际上...模块的'模块类'是'类的类'这个类的父类.搞懂了吗?不懂?让我们继续看
我有一个脚本,它从 CLI 获取 3 个输入变量并将其分别插入到 3 个变量: GetOptions("old_path=s" => \$old_path, "var=s" =
我有一个简单的 python 包,其目录结构如下: wibble | |-----foo | |----ping.py | |-----bar | |----pong.py 简单的
这种语法会非常有用——这不起作用有什么原因吗?谢谢! module Foo = { let bar: string = "bar" }; let bar = Foo.bar; /* works *
我想运行一个命令: - name: install pip shell: "python {"changed": true, "cmd": "python <(curl https://boot
我是一名优秀的程序员,十分优秀!