一.Python中的上下文管理器(contextlib模块)

上下文管理器的任务是:代码块执行前准备,代码块执行后收拾

1、如何使用上下文管理器:

如何打开一个文件,并写入"hello world"

filename="my.txt"
mode="w"
f=open(filename,mode)
f.write("hello world")
f.close()

当发生异常时(如磁盘写满),就没有机会执行第5行。当然,我们可以采用try-finally语句块进行包装:

writer=open(filename,mode)
try:
writer.write("hello world")
finally:
writer.close()

当我们进行复杂的操作时,try-finally语句就会变得丑陋,采用with语句重写:

with open(filename,mode) as writer:
writer.write("hello world")

as指代了从open()函数返回的内容,并把它赋给了新值。with完成了try-finally的任务。

2、自定义上下文管理器  

with语句的作用类似于try-finally,提供一种上下文机制。要应用with语句的类,其内部必须提供两个内置函数__enter__和__exit__。前者在主体代码执行前执行,后者在主体代码执行后执行。as后面的变量,是在__enter__函数中返回的。

class echo():
def output(self):
print "hello world"
def __enter__(self):
print "enter"
return self #可以返回任何希望返回的东西
def __exit__(self,exception_type,value,trackback):
print "exit"
if exception_type==ValueError:
return True
else:
return Flase >>>with echo as e:
e.output() 输出:
enter
hello world
exit

完备的__exit__函数如下:

def __exit__(self,exc_type,exc_value,exc_tb)

其中,exc_type:异常类型;exc_value:异常值;exc_tb:异常追踪信息

当__exit__返回True时,异常不传播

3、contextlib模块  

contextlib模块的作用是提供更易用的上下文管理器,它是通过Generator实现的。contextlib中的contextmanager作为装饰器来提供一种针对函数级别的上下文管理机制,常用框架如下:

from contextlib import contextmanager
@contextmanager
def make_context():
print('enter')
try:
yield "ok"
except RuntimeError as err:
print('error',err)
finally:
print('exit') with make_context() as value:
print value 输出为:
enter
ok
exit

其中,yield写入try-finally中是为了保证异常安全(能处理异常)as后的变量的值是由yield返回。yield前面的语句可看作代码块执行前操作,yield之后的操作可以看作在__exit__函数中的操作。

以线程锁为例:

# -*- coding: utf-8 -*-
# 2017/11/24 17:22
from contextlib import contextmanager
import threading lock = threading.Lock() @contextmanager
def loudLock():
print('Locking')
lock.acquire()
yield
print('Releasing')
lock.release() with loudLock():
print('Lock is locked: %s' % lock.locked())
print('Doing something that needs locking') # Output: # Locking
# Lock is locked: True
# Doing something that needs locking
# Releasing

4、contextlib.closing() 

file类直接支持上下文管理器API,但有些表示打开句柄的对象并不支持,如urllib.urlopen()返回的对象。还有些遗留类,使用close()方法而不支持上下文管理器API。为了确保关闭句柄,需要使用closing()为它创建一个上下文管理器(调用类的close方法)。

# -*- coding: utf-8 -*-
# 2017/11/24 17:30
import contextlib class myclass():
def __init__(self):
print('__init__') def close(self):
print('close()') with contextlib.closing(myclass()):
print('ok') 输出:
__init__
ok
close()

二.queue模块

创建一个“队列”对象
import Queue
q = Queue.Queue(maxsize = 10)
Queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。

将一个值放入队列中
q.put(10)
调用队列对象的put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为
1。如果队列当前为空且block为1,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为0,put方法将引发Full异常。

将一个值从队列中取出
q.get()
调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False,队列将引发Empty异常。

Python Queue模块有三种队列及构造函数:
1、Python Queue模块的FIFO队列先进先出。  class queue.Queue(maxsize)
2、LIFO类似于堆,即先进后出。             class queue.LifoQueue(maxsize)
3、还有一种是优先级队列级别越低越先出来。   class queue.PriorityQueue(maxsize)

此包中的常用方法(q = Queue.Queue()):
q.qsize() 返回队列的大小
q.empty() 如果队列为空,返回True,反之False
q.full() 如果队列满了,返回True,反之False
q.full 与 maxsize 大小对应
q.get([block[, timeout]]) 获取队列,timeout等待时间
q.get_nowait() 相当q.get(False)

q.put(item) 写入队列,timeout等待时间
q.put_nowait(item) 相当q.put(item, False)
q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号
q.join() 实际上意味着等到队列为空,再执行别的操作

from random import randrange
from time import sleep,ctime
from queue import Queue import threading class MyThread(threading.Thread):
def __init__(self, func, args, name='', verb=False):
threading.Thread.__init__(self)
self.name = name
self.func = func
self.args = args
self.verb = verb def getResult(self):
return self.res def run(self):
if self.verb:
print('starting', self.name, 'at:', ctime())
self.res = self.func(*self.args)
if self.verb:
print(self.name, 'finished at:', ctime()) def writeQ(queue):
print('producing object for Q...', end='')
queue.put('xxx', 1)
print("size now", queue.qsize()) def readQ(queue):
val = queue.get(1)
print('consumed object from Q... size now', queue.qsize()) def writer(queue, loops):
for i in range(loops):
writeQ(queue)
sleep(randrange(1, 4)) def reader(queue, loops):
for i in range(loops):
readQ(queue)
sleep(randrange(2, 6)) funcs = [writer, reader]
nfuncs = range(len(funcs)) def main():
nloops = randrange(2, 6)
q = Queue(32) threads = []
for i in nfuncs:
t = MyThread(funcs[i], (q, nloops),funcs[i].__name__)
threads.append(t) for i in nfuncs:
threads[i].start() for i in nfuncs:
threads[i].join() print('all DONE') if __name__ == '__main__':
main()

queue

三 自定义线程池

# -*- coding: utf-8 -*-
# 2017/11/25 12:54
import queue
import threading class ThreadPool(object):
def __init__(self, max_num=20):
self.queue = queue.Queue(max_num)
for i in range(max_num):
self.queue.put(threading.Thread) def get_thread(self):
return self.queue.get() def add_thread(self):
self.queue.put(threading.Thread) pool = ThreadPool(10) def func(arg, p):
print(arg)
import time
time.sleep(2)
p.add_thread() for i in range(30):
thread = pool.get_thread()
t = thread(target=func, args=(i, pool))
t.start()
# -*- coding: utf-8 -*-
# 2017/11/25 13:00
import queue
import threading
import contextlib
import time StopEvent = object() class ThreadPool(object):
def __init__(self, max_num, max_task_num = None):
if max_task_num:
self.q = queue.Queue(max_task_num)
else:
self.q = queue.Queue()
self.max_num = max_num
self.cancel = False
self.terminal = False
self.generate_list = []
self.free_list = [] def run(self, func, args, callback=None):
"""
线程池执行一个任务
:param func: 任务函数
:param args: 任务函数所需参数
:param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数
1、任务函数执行状态;2、任务函数返回值(默认为None,即:不执行回调函数)
:return: 如果线程池已经终止,则返回True否则None
"""
if self.cancel:
return
if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
self.generate_thread()
w = (func, args, callback,)
self.q.put(w) def generate_thread(self):
"""
创建一个线程
"""
t = threading.Thread(target=self.call)
t.start() def call(self):
"""
循环去获取任务函数并执行任务函数
"""
current_thread = threading.currentThread()
self.generate_list.append(current_thread)
event = self.q.get()
while event != StopEvent:
func, arguments, callback = event
try:
result = func(*arguments)
success = True
except Exception as e:
success = False
result = None
if callback is not None:
try:
callback(success, result)
except Exception as e:
pass
with self.worker_state(self.free_list, current_thread):
if self.terminal:
event = StopEvent
else:
event = self.q.get()
else:
self.generate_list.remove(current_thread) def close(self):
"""
执行完所有的任务后,所有线程停止
"""
self.cancel = True
full_size = len(self.generate_list)
while full_size:
self.q.put(StopEvent)
full_size -= 1 def terminate(self):
"""
无论是否还有任务,终止线程
"""
self.terminal = True
while self.generate_list:
self.q.put(StopEvent)
self.q.queue.clear() @contextlib.contextmanager
def worker_state(self, state_list, worker_thread):
"""
用于记录线程中正在等待的线程数
"""
state_list.append(worker_thread)
try:
yield
finally:
state_list.remove(worker_thread) # How to use pool = ThreadPool(5) def callback(status, result):
# status, execute action status
# result, execute action return value
pass def action(i):
print(i) for i in range(30):
ret = pool.run(action, (i,), callback) time.sleep(5)
print(len(pool.generate_list), len(pool.free_list))
print(len(pool.generate_list), len(pool.free_list))
pool.close()
pool.terminate()

edition2

Python多线程编程(第二篇)的更多相关文章

  1. python核心编程第二版笔记

    python核心编程第二版笔记由网友提供:open168 python核心编程--笔记(很详细,建议收藏) 解释器options:1.1 –d   提供调试输出1.2 –O   生成优化的字节码(生成 ...

  2. 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq

    5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...

  3. 关于python多线程编程中join()和setDaemon()的一点儿探究

    关于python多线程编程中join()和setDaemon()的用法,这两天我看网上的资料看得头晕脑涨也没看懂,干脆就做一个实验来看看吧. 首先是编写实验的基础代码,创建一个名为MyThread的  ...

  4. Python核心编程(第二版)PDF

    Python核心编程(第二版) 目录 第1部分 Python核心第1章 欢迎来到Python世界1.1 什么是Python1.2 起源1.3 特点1.3.1 高级1.3.2 面向对象1.3.3 可升级 ...

  5. Python并发编程理论篇

    Python并发编程理论篇 前言 其实关于Python的并发编程是比较难写的一章,因为涉及到的知识很复杂并且理论偏多,所以在这里我尽量的用一些非常简明的语言来尽可能的将它描述清楚,在学习之前首先要记住 ...

  6. python多线程编程

    Python多线程编程中常用方法: 1.join()方法:如果一个线程或者在函数执行的过程中调用另一个线程,并且希望待其完成操作后才能执行,那么在调用线程的时就可以使用被调线程的join方法join( ...

  7. Python开发【第二篇】:初识Python

    Python开发[第二篇]:初识Python   Python简介 Python前世今生 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏 ...

  8. day-3 python多线程编程知识点汇总

    python语言以容易入门,适合应用开发,编程简洁,第三方库多等等诸多优点,并吸引广大编程爱好者.但是也存在一个被熟知的性能瓶颈:python解释器引入GIL锁以后,多CPU场景下,也不再是并行方式运 ...

  9. 拒绝从入门到放弃_《Python 核心编程 (第二版)》必读目录

    目录 目录 关于这本书 必看知识点 最后 关于这本书 <Python 核心编程 (第二版)>是一本 Python 编程的入门书,分为 Python 核心(其实并不核心,应该叫基础) 和 高 ...

  10. 少儿编程:python趣味编程第二课,如何在pygame中写文字

    python趣味编程第二课:本文仅针对8-16岁的青少年,所以流程是按如何去教好中小学生走的,并不适合成人找工作学习,因为进度也是按照青少年走的 大家好,我是C大叔,上一篇文章已经跟大家介绍了一款开发 ...

随机推荐

  1. 家居环境监測系统设计(PC上位机版)(手机APP版待定)

    下面是我的毕业设计:家居环境监測系统设计(PC上位机临时版.手机app版待定).本系统採用STC12C5A60S2单片机.结合传感器.分别对空气湿度.空气温度.气压.海拔.进水温度.出水温度.光照强度 ...

  2. MAC系统里JDK版本切换

    1.首先安装需要的JDK版本 JDK7,JDK8则需要自己到Oracle官网下载安装对应的版本.自己安装的JDK默认路径为:/Library/Java/JavaVirtualMachines/jdk1 ...

  3. MySQL datetime的更新,删除网上的一些老概念

    网上的老概念 第一点:是以前的MySQL的datetime的最小值是:'1000-01-01 00:00:00'(貌似),但是最新的MySQL测试datetime的最小值可以是:'0000-00-00 ...

  4. Python3.5:爬取网站上电影数据

    首先我们导入几个pyhton3的库: from urllib import requestimport urllibfrom html.parser import HTMLParser 在Python ...

  5. ROS初探:(一)ROS架构

    一.ROS架构 ROS架构上分为三个层级: 计算图级(Computation Graph level):体现进程与系统的关系,描述系统怎么运行. 文件系统级(Filesystem level):组织构 ...

  6. ArcGIS API for JavaScript 4.2学习笔记[28] 可视域分析【使用Geoprocessor类】

    想知道可视域分析是什么,就得知道可视域是什么 我们站在某个地方,原地不动转一圈能看到的所有事物就叫可视域.当然平地就没什么所谓的可视域. 如果在山区呢?可视范围就会被山体挡住了.这个分析对军事上有十分 ...

  7. bzoj 4539: [Hnoi2016]树

    Description 小A想做一棵很大的树,但是他手上的材料有限,只好用点小技巧了.开始,小A只有一棵结点数为N的树,结 点的编号为1,2,-,N,其中结点1为根:我们称这颗树为模板树.小A决定通过 ...

  8. bzoj 3894: 文理分科

    Description  文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过)  小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位. ...

  9. PredictionIO+Universal Recommender快速开发部署推荐引擎的问题总结(2)

    1, 对Universal Recommender进行pio build成功,但是却提示No engine found Building and delpoying model [INFO] [Eng ...

  10. dd 命令详解

    作用: dd 是一个Unix和类Unix系统中的命令, 主要功能为转换和赋值文件.在Unix和类Unix系统上, 硬件的设备驱动(如硬盘) 和特殊设备文件(如/dev/zero, /dev/rando ...