python 笔记二
17.进程线程
进程间通信方式:管道Pipe;队列Queue;共享内存Value、Array、Manager;
多进程同步:锁Lock、递归锁RLock、Condition(条件变量);事件event;信号signal;信号量Semaphore;
- 函数方式
from multiprocessing import Process
import time
import os def test(sub_p):
for j in range(20):
print('%s----pid=%s' % (sub_p, os.getpid()))
time.sleep(1) for i in range(3):
p = Process(target=test, name='sub_%s' % i, args=(i,))
print('sub process %s' % p.name)
p.start()
p.join(5) # join表示延时时间,也就是等待子进程的时间,当10秒过了以后,则会运行主进程。 for i in range(60):
print('----')
time.sleep(1)
- 类的方式
from multiprocessing import Process
import time
import os class ProcessClass(Process):
def __init__(self, sub_p):
super(ProcessClass, self).__init__()
self.sub_p = sub_p def run(self): # 重写run方法,当调用start方法时,则会默认调用run方法,所以不用再填写target参数。
for j in range(20):
print('%s----pid=%s' % (self.sub_p, os.getpid()))
time.sleep(1) for i in range(3):
p = ProcessClass(i)
p.start()
p.join(5) # 这里将会等待子进程单独运行5秒。 for i in range(60): # 主进程,当join等待结束收,则会父子进程一起运行。但是如果当父进程运行完,子进程还没有结束,那么父进程会继续等子进程。
print('--main--')
time.sleep(1)
- 进程池pool
| 方法 | 描述 |
| apply() | 以同步方式添加进程 |
| apply_async() | 以异步方式添加进程 |
| close() | 关闭Pool,使其不接受新任务(还可以使用) |
| terminate() | 不管任务是否完成,立即终止 |
| join() | 主进程阻塞,等待子进程的退出,必须在close和terminate后使用 |
from multiprocessing import Pool # 导入Pool模块类
import os
import time def work(num):
print('进程的pid是%d,进程值是%d' % (os.getpid(), num))
time.sleep(2) p = Pool(2) # 实例化对象,参数2表示创建2个子进程,就是说每次只能执行2个进程。 for i in range(6):
print('--%d--' % i)
# 向实例对象添加6次任务,就是6个进程,但是实例对象的进程池只有2个,所以每次往进程池中放2个进程,
# 当进程池中的2个进程执行完以后,再允许向进程池中添加进程。
p.apply_async(work, (i,)) p.close() # 关闭进程池,不再接收进程任务。
p.join() # 当子进程工作结束后,则会运行主进程。
- 进程间通信:Queue消息队列
| 方法 | 描述 |
| put | q.put(数据),放入数据(如队列已满,则程序进入阻塞状态,等待队列取出后再放入) |
| put_nowait | q.put_nowati(数据),放入数据(如队列已满,则不等待队列取出后再放入,直接报错) |
| get | q.get(数据),取出数据(如队列为空,阻塞等待队列放入数据后再取出) |
| get_nowait | q.get_nowait(数据),取出数据(如队列为空,不等待队列取出之前数据,直接报错),放入数据后立马判断是否为空有时为True,原因是放入值和判断同时进行 |
| qsize | q.qsize() 消息数量 |
| empty | q.empty() 返回True或False,判断是否为空 |
| full | q.full() 返回值为True或False,判断是否为满 |
- 进程间通信:Pipe管道

from multiprocessing import Process, Pipe def f(conn):
conn.send([1, 'test', None])
conn.send([2, 'test', None])
print('child get: %s' % conn.recv()) # 没数据时读阻塞
conn.close() if __name__ == "__main__":
# Pipe(duplex=True)返回管道的两端,duplex=True时双向管道;False时单向parent_conn只读,child_conn只写
parent_conn, child_conn = Pipe(duplex=True)
p = Process(target=f, args=(child_conn,))
p.start()
res = parent_conn.recv()
print('parent get: %s, type=%s' % (res, type(res)))
print('parent get: %s' % parent_conn.recv())
parent_conn.send('father test')
p.join()
- 进程间通信,共享数据:value+array, Manager
Python中进程间共享数据,处理基本的queue,pipe和value+array外,还提供了更高层次的封装。使用multiprocessing.Manager可以简单地使用这些高级接口。
Manager()返回的manager对象控制了一个server进程,此进程包含的python对象可以被其他的进程通过proxies来访问。从而达到多进程间数据通信且安全。
Manager支持的类型有:list,dict,Namespace,Lock,RLock,Semaphore,BoundedSemaphore,Condition,Event,Queue,Value和Array。
from multiprocessing import Manager, Process, Lock def work(d, lock):
with lock: # 不加锁而操作共享的数据,肯定会出现数据错乱
d['count'] -= 1 if __name__ == '__main__':
lock = Lock()
with Manager() as m:
dic = m.dict({'count': 100})
p_l = []
for i in range(100):
p = Process(target=work, args=(dic, lock))
p_l.append(p)
p.start()
for p in p_l:
p.join()
print(dic)
注意:
使用Manager可以方便的进行多进程数据共享,但当使用Manager处理list、dict等可变数据类型时,需要非常注意一个陷阱。看下面的代码:
from multiprocessing import Process, Manager manager = Manager()
m = manager.list()
m.append({'id':1}) def test():
m[0]['id'] = 2 p = Process(target=test)
p.start()
p.join()
print(m[0])
执行结果是:{'id': 1},不是预期的:{'id': 2}要达到预期的结果,代码应改为:
from multiprocessing import Process, Manager manager = Manager()
m = manager.list()
m.append({'id':1}) def test():
hack = m[0]
hack['id'] = 2
m[0] = hack p = Process(target=test)
p.start()
p.join()
print(m[0])
以上代码中让人困惑的操作的目的是绕过Manager的一个隐秘问题,这个问题是指:Manager对象无法监测到它引用的可变对象值的修改,需要通过触发__setitem__方法来让它获得通知
python 笔记二的更多相关文章
- Python笔记(二)
python笔记 函数式编程 函数 函数是Python内建支持一种封装(将大段代码拆成函数) 通过函数的调用,可以将复制的任务分解. 函数式编程(Functional Programming) 计算机 ...
- python笔记二(数据类型和变量、编码方式、字符串的编码、字符串的格式化)
一.数据类型 python可以直接处理的数据类型有:整数.浮点数.字符串.布尔值.空值. 整数 浮点数 字符串:双引号内嵌套单引号,可以输出 i'm ok. 也可以用\来实现,\n 换行 \t tab ...
- guxh的python笔记二:函数基础
1,函数的参数 1.1,查看函数的参数类型 def run(a, *args, b, **kwargs): return a + b 可以通过如下方式查看参数类型: import inspect k ...
- python笔记二
一 运算符 1算术运算+ - * / % ** //其中%为取余,**为取幂如2**10=1024 9//4=2 需要注意的是python2.7中如9/2=4 需要正确表示,则在开头添加 fr ...
- python笔记二(mysql数据库操作)
python2.x使用MySQLdb python3.x使用pymysql代替MySQLdb 不过我使用的是python3.5,MySQLdb还是可以在python3.5使用的. #!/usr/bin ...
- Python笔记(二)查找重复元素
一.查找数列重复元素---count() >>> list = [,,,,,,,,,,,] >>> set = set(list) >>> for ...
- Python笔记(二十九)_模块
模块 在Python中,一个.py文件就是一个模块 if __name__ == '__main__':所有模块都有一个 __name__ 属性,__name__ 的值取决于如何应用模块 run当前文 ...
- Python笔记(二十六)_魔法方法_属性的魔法方法
属性的魔法方法 __getattribute__(self,name):当该类的属性被访问时,自动触发,是最先被触发的属性方法 __setattr__(self,name,value):当一个属性被设 ...
- Python笔记(二十四)_魔法方法_运算符的魔法方法
算数运算方法 .反运算方法 以对象A+对象B为例,都是将A作为self值,而B作为other值传入__add__(self,other)方法: 当用户输入A+B,就会调用重写的add方法: >& ...
随机推荐
- SpringMVC 给请求路径加上统一前缀
最开始想到的是通过硬编码的方式手动在每个路径上加上前缀, 后面发现这种方式太不智能了,万一要修改那还不得改死, Spring既然支持EL表达式, 那能不能通过EL表达式的方式去读取配置文件里面的属性来 ...
- git : error occurred during unpacking on the remote end: unpack-objects abnormal exit
error occurred during unpacking on the remote end: unpack-objects abnormal exit git服务器磁盘满了.
- Solidity truffle,部署合约到Ropsten测试链或主链,调用合约(转)
Solidity truffle,部署合约到Ropsten测试链或主链,调用合约 转 https://blog.csdn.net/houyanhua1/article/details/89010896 ...
- SpringBoot MAVEN编译报错Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:
参考了好几篇文章没搞定,直到查询错误关键字 An unknown compilation problem occurred 分别参考了以下博客: https://blog.csdn.net/fanre ...
- 采用EasyDSS视频点播服务器搭建企业私有化的音视频多媒体、短视频、视频服务网站与管理后台
最近有越来越多的用户咨询关于视频点播的功能,主要需求就是集中于如何搭建专属的私有化视频点播平台: 实现的功能类似于,对应自身拥有的视频文件,需要发布到一个网站,其他用户都可以实现点播观看. 针对于类似 ...
- Linux安装卸载JDK完整步骤
1.检查一下系统中的jdk版本 [root@localhost software]# java -version 显示: openjdk version "1.8.0_102" O ...
- python实践项目五:操作剪贴板-pyperclip模块
描述:读取剪贴板的内容,修改该内容,再将修改后的内容重新写进剪贴板 注意:执行程序代码前需保证剪贴板有内容,可复制以下内容来测试: Lists of animals Lists of aquarium ...
- LeetCode 1051. 高度检查器(Height Checker) 28
1051. 高度检查器 1051. Height Checker 题目描述 学校在拍年度纪念照时,一般要求学生按照 非递减 的高度顺序排列. 请你返回至少有多少个学生没有站在正确位置数量.该人数指的是 ...
- java.IO.EOFException异常
错误代码为: 43 boolean booleanResult = dis.readBoolean();//dis为DateInputStream的实例 44 System.out.println(b ...
- SVN:修改文件后提示感叹号消失了处理办法
使用SVN发现文件修改后,默认的修改标记红色感叹号不见了 重新显示设置方法: [右键]——[TortoiseSVN]——[Setting] 在[Icon Overlays]中选择[Default]即可 ...