封面图片来源:沙沙野

内容概览

  1. 进程的 join 方法
  2. 数据隔离
  3. 进程对象的其他方法
  4. 守护进程
  5. 抢票程序示例
  6. 队列
  7. 进程之间的通信 (IPC)

进程的 join 方法

  1. 假设要群发 1000 封邮件,发一封要 0.1s,那么发完也要 100s。如果不想这么久,就可以使用进程
from multiprocessing import Processdef send_mail(n):print("发送邮件%s" % n)if __name__ == "__main__":p = Process(target=send_mail, args=(1,))p.start()# 阻塞,直到子进程执行结束p.join()  print("所有的邮件都发送完了")# 运行结果:
发送邮件1
所有的邮件都发送完了# 使用join()能够保证先打印 发送邮件,再打印 所有的邮件都发送完了

2. 同步发送邮件

from multiprocessing import Processdef send_mail(n):print("发送邮件%s" % n)if __name__ == "__main__":for i in range(10):p = Process(target=send_mail, args=(i,))p.start()p.join()print("所有的邮件都发送完了")# 运行结果:
发送邮件0
发送邮件1
发送邮件2
发送邮件3
发送邮件4
发送邮件5
发送邮件6
发送邮件7
发送邮件8
发送邮件9
所有的邮件都发送完了# 同步执行,意思就是上面的 0-9 的运行结果一定是按顺序的

3. 为了节省时间,应该让子进程运行的时候是异步的

from multiprocessing import Processdef send_mail(n):print("发送邮件%s" % n)if __name__ == "__main__":l = []for i in range(10):p = Process(target=send_mail, args=(i,))l.append(p)p.start()for p in l:p.join()print("所有的邮件都发送完了")# 运行结果:
发送邮件0
发送邮件1
发送邮件2
发送邮件4
发送邮件5
发送邮件6
发送邮件7
发送邮件3
发送邮件9
发送邮件8
所有的邮件都发送完了# 异步执行,说明多个进程在同一时刻进行
# 因此这里的 0-9 的结果不一定按顺序运行
from multiprocessing import Process
import timeprint("这是函数外部")def func():time.sleep(5)print("子进程开始运行")if __name__ == "__main__":p = Process(target=func)print("这是在子进程启动之前")p.start()print(p.is_alive())p.join()print(p.is_alive())print("主进程开始执行")# 运行结果:
这是函数外部
这是在子进程启动之前
True
子进程开始运行
False
主进程开始执行

数据隔离

n = 100
def func():global nn -= 1for i in range(100):func()
print(n)from multiprocessing import Process
n = 100
def func():global nn -= 1if __name__ == "__main__":p_list = []for i in range(100):p = Process(target=func)p.start()p_list.append(p)for p in p_list:p.join()print(n)# 运行结果:
0
100# 100 要等一会才会出结果,因为有join()
# 在进程之间数据是完全不能互通的

进程对象的其他方法

from multiprocessing import Process
import timeclass MyProcess(Process):# 给子进程传递参数def __init__(self, a, b): super().__init__()self.a = aself.b = bdef run(self):print("子进程开始执行")time.sleep(2)print("子进程结束", self.a, self.b)if __name__ == "__main__":p = MyProcess(1, 2)p.start()print(p.is_alive())time.sleep(1)print(p.name)p.terminate()   # 非阻塞print(p.is_alive())time.sleep(0.5)print(p.is_alive())# 运行结果:
True
子进程开始执行
MyProcess-1
True
False

守护进程

  1. 一般用法:在开启子进程之前可以设置子进程为守护进程,p.daemon = True。守护进程随着主进程的代码执行结束而结束
import time
from multiprocessing import Processdef eye():while True:print("我是子进程, 告诉server端我很好")time.sleep(2)def main():print("我想做的事情")if __name__ == "__main__":p = Process(target=eye)p.start()main()# 运行结果:
我想做的事情
我是子进程, 告诉server端我很好
我是子进程, 告诉server端我很好
我是子进程, 告诉server端我很好
我是子进程, 告诉server端我很好
我是子进程, 告诉server端我很好
我是子进程, 告诉server端我很好
...# 因为设置了时间延迟,因此先执行主进程的 main()
# 另外,每隔 2s 执行子进程

2. 只要主进程的代码结束,子进程也会随之结束

import timefrom multiprocessing import Processdef eye():while True:print("我是守护进程, 每隔2s告诉server端我很好")time.sleep(2)def main():print("我是主进程, 5s后我将结束运行")time.sleep(5)print("主进程结束后,守护进程也不再执行")if __name__ == "__main__":p = Process(target=eye)p.daemon = True     # p进程设置成 守护进程p.start()main()# 运行结果:
我是主进程, 5s后我将结束运行
我是守护进程, 每隔2s告诉server端我很好
我是守护进程, 每隔2s告诉server端我很好
我是守护进程, 每隔2s告诉server端我很好
主进程结束后,守护进程也不再执行

3. 守护进程只守护主进程,不会守护子进程

import time
from multiprocessing import Processdef eye():while True:print("我是守护进程, 我只守护主进程,每隔2s告诉server端我很好")time.sleep(2)def process2():print("我是子进程, 8s后我就结束运行,守护进程不会守护我")time.sleep(8)print("我是子进程, 我现在结束运行,主进程也跟着结束")def main():print("我是主进程,5s后我将结束运行")time.sleep(5)print("5s过去了,但是子进程还没结束,要等它结束我才能结束")if __name__ == "__main__":p = Process(target=eye)p2 = Process(target=process2)p.daemon = True  # p进程设置成 守护进程p.start()p2.start()main()# 运行结果:
我是主进程,5s后我将结束运行
我是守护进程, 我只守护主进程,每隔2s告诉server端我很好
我是子进程, 8s后我就结束运行,守护进程不会守护我
我是守护进程, 我只守护主进程,每隔2s告诉server端我很好
我是守护进程, 我只守护主进程,每隔2s告诉server端我很好
5s过去了,但是子进程还没结束,要等它结束我才能结束
我是子进程, 我现在结束运行,主进程也跟着结束

4. 总结:守护进程会随着主进程代码的结束而结束,不会守护除了主进程代码之外的其他子进程

import time
from multiprocessing import Processdef eye():while True:print("我是守护进程, 我现在守护主进程和子进程,每隔2s告诉它们我很好")time.sleep(2)def process2():print("我是子进程,12s后我就结束运行")time.sleep(12)print("我是子进程,我现在结束运行")def main():print("我是主进程,5s后我就结束运行")time.sleep(5)print("我是主进程,我现在结束运行")if __name__ == "__main__":p = Process(target=eye)p2 = Process(target=process2)p.daemon = True  # p进程设置成 守护进程p.start()p2.start()main()p2.join()# p2 结束之后这句代码才会结束
# 如果想让守护进程守护子进程,则像上面这样把子进程加个 join 就行# 运行结果:
我是主进程,5s后我就结束运行
我是守护进程, 我现在守护主进程和子进程,每隔2s告诉它们我很好
我是子进程,12s后我就结束运行
我是守护进程, 我现在守护主进程和子进程,每隔2s告诉它们我很好
我是守护进程, 我现在守护主进程和子进程,每隔2s告诉它们我很好
我是主进程,我现在结束运行
我是守护进程, 我现在守护主进程和子进程,每隔2s告诉它们我很好
我是守护进程, 我现在守护主进程和子进程,每隔2s告诉它们我很好
我是守护进程, 我现在守护主进程和子进程,每隔2s告诉它们我很好
我是守护进程, 我现在守护主进程和子进程,每隔2s告诉它们我很好
我是子进程,我现在结束运行

抢票程序:使用多进程实现 socket tcp 协议 server 端的并发

  1. server.py
import socket
from multiprocessing import Processdef func(conn):while 1:conn.send("我会一直向客户端发送这个信息".encode())if __name__ == "__main__":sk = socket.socket()sk.bind(("127.0.0.1", 8080))sk.listen()while 1:conn, addr = sk.accept()p = Process(target=func, args=(conn,))p.start()

2. 创建多个同样内容的 client.py

import socketsk = socket.socket()
sk.connect(("127.0.0.1", 8080))while True:msg = sk.recv(1024)print(msg.decode())# 运行结果都一样:
我会一直向客户端发送这个信息
我会一直向客户端发送这个信息
我会一直向客户端发送这个信息
...

3. 抢票示例

# 先查看余票,再抢票,注意是并发
# 先创建一个 ticket 的文件, 内容如下:
# {"count": 3}
# 3 表示还有 3 张票import json
import time
from multiprocessing import Process
from multiprocessing import Lockdef search(name):with open("ticket") as f:ticket_count = json.load(f)if ticket_count["count"] >= 1:print("%s号注意了: 有余票%s张" % (name, ticket_count["count"]))else:print("%s号注意: 没票了" % name)def buy(name):with open("ticket") as f:ticket_count = json.load(f)time.sleep(0.2)if ticket_count["count"] >= 1:print("有余票%s张" % ticket_count["count"])ticket_count["count"] -= 1print("%s号买到票了" % name)else:print("%s号没买到票" % name)with open("ticket", "w") as f:json.dump(ticket_count, f)def opt(lock, name):search(name)lock.acquire()buy(name)lock.release()if __name__ == "__main__":lock = Lock()       # 锁,保证数据安全,不超票for i in range(10):p = Process(target=opt, args=(lock, "alex"+str(i),))p.start()# 运行结果:
alex0号注意了: 有余票3张
alex1号注意了: 有余票3张
alex2号注意了: 有余票3张
alex3号注意了: 有余票3张
alex4号注意了: 有余票3张
alex5号注意了: 有余票3张
alex6号注意了: 有余票3张
alex7号注意了: 有余票3张
alex8号注意了: 有余票3张
alex9号注意了: 有余票3张
有余票3张
alex0号买到票了
有余票2张
alex1号买到票了
有余票1张
alex2号买到票了
alex3号没买到票
alex4号没买到票
alex5号没买到票
alex6号没买到票
alex7号没买到票
alex8号没买到票
alex9号没买到票# 多个进程抢占同一个数据资源会造成数据不安全
# 必须要牺牲效率来保证数据的安全性
# 什么时候用到锁?
# 当多个进程使用同一份数据资源的时候/操作文件、操作共享数据、操作数据库等

队列:维护了一个秩序,先进先出,FIFO (first in first out)

import queueq = queue.Queue()
print(q)        # <queue.Queue object at 0x0000029753908710>
q.put(1)
q.put(2)
q.put(3)
print(q)        # <queue.Queue object at 0x0000029753908710>print(q.get())  # 1
print(q.get())  # 2
print(q.get())  # 3

进程之间的通信: IPC (Iter Process Communication)

from multiprocessing import Queue, Processdef son(q):msg1 = q.get()print(msg1)msg2 = q.get()print(msg2)msg3 = q.get()print(msg3)if __name__ == "__main__":q = Queue()  # 队列是进程之间数据安全的数据类型,基于pickle + socket + Lockpro = Process(target=son, args=(q, ))pro.start()q.put("我是第一个被放进去的,取数据的时候我第一个出来")q.put("我是第二个被放进去的")q.put("我是最后被放进去的")# 运行结果:
我是第一个被放进去的,取数据的时候我第一个出来
我是第二个被放进去的
我是最后被放进去的# 还有一个管道Pipe,没有锁,数据不安全,这里暂不了解其用法
# 其实队列就是管道+锁的结合# 第三方工具(消息中间件):memocache, redis, kafka, rabbitmq
# 都是实现进程之间的通信的桥梁
# 队列的用法+模型

vc sleep不占进程_Python 中的进程深入相关推荐

  1. linux多进程server 进程池_Python 中的进程池与多进程

    封面图片来源:沙沙野 内容概览 进程池 进程池和多进程的性能测试 进程池的其他机制 进程池的回调函数 进程池 如果有多少个任务,就开启多少个进程,实际上并不划算.由于计算机的 cpu 个数是非常有限的 ...

  2. python僵尸进程和孤儿进程_python中多进程应用及僵尸进程、孤儿进程

    一.python如何使用多进程 创建子进程的方式 1.导入multiprocessing 中的Process类 实例化这个类 指定要执行的任务 target import os from multip ...

  3. python中线程和进程_python中线程和进程的简单了解

    一.操作系统.应用程序 1.硬件:硬盘.cpu.主板.显卡........ 2.装系统(本身也是一个软件): 系统就是一个由程序员写出来的软件,该软件用于控制计算机得硬盘,让他们之间进行互相配合. 3 ...

  4. python协程怎么做数据同步_Python 中的进程、线程、协程、同步、异步、回调

    进程和线程究竟是什么东西?传统网络服务模型是如何工作的?协程和线程的关系和区别有哪些?IO过程在什么时间发生? 一.上下文切换技术 简述 在进一步之前,让我们先回顾一下各种上下文切换技术. 不过首先说 ...

  5. python进程process类返回值_Python 中的进程

    封面图片来源:沙沙野 内容概览进程必备的理论基础 进程的概念 并行和并发 进程的三状态 同步异步 进程模块 关于进程必备的理论基础操作系统的作用隐藏丑陋复杂的硬件接口,提供良好的抽象接口 管理.调度进 ...

  6. pythonmultiprocessing之 queue线程_python中的进程、线程(threading、multiprocessing、Queue、subprocess)...

    Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CP ...

  7. python进程池和线程池_Python中的进程池与线程池(包含代码)

    引入进程池与线程池 使用ProcessPoolExecutor进程池,使用ThreadPoolExecutor 使用shutdown 使用submit同步调用 使用submit异步调用 异步+回调函数 ...

  8. python创建新进程_Python并发编程(进程的创建)

    动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的. 并发性:任何进程都可以同其他进程一起并发执行 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的 ...

  9. python守护进程_Python实现守护进程

    考虑如下场景:你编写了一个python服务程序,并且在命令行下启动,而你的命令行会话又被终端所控制,python服务成了终端程序的一个子进程.因此如果你关闭了终端,这个命令行程序也会随之关闭. 要使你 ...

最新文章

  1. 关于校验规则(Validation Rule)和业务规则(Bussiness Rule)的思考
  2. 记一次修复被篡改的IE首页
  3. 《图解CSS3:核心技术与案例实战》——1.1节什么是CSS3
  4. shell脚本输出菱形与等边三角形
  5. boost::all_clustering_coefficients用法的测试程序
  6. hadoop2.2单节点集群的搭建
  7. 用ghost备份和还原Linux系统
  8. MySQL服务器意外关机-无法启动多实例
  9. OpenGL ES和EGL关系(二十五)
  10. vue2.0中 怎么引用less?
  11. 洛谷 P1168 中位数 堆
  12. php libiconv close_无法编译PHP undefined reference to `libiconv_open
  13. win7触摸板怎么关闭_笔记本电脑触摸板快速关闭,避免误碰影响操作
  14. 佛理(引用别人的东西,怕忘记了不好找,拿来了,哈哈)
  15. directadmin php5.6,Directadmin 1.53开心版 安装教程
  16. 结构化设计(实验二)
  17. 深度学习笔记~集成方法bagging, boosting和stacking
  18. 【附源码】Python计算机毕业设计软件缺陷管理系统
  19. 台式计算机品牌及价格,全球十大台式电脑品牌 联想拥有良好的品质和适合的价格...
  20. java clip_java – 使用Clip对象播放多个声音片段

热门文章

  1. ubuntu 下 github 使用方法 以及异常修改
  2. ARM上的Bootloader的具体实现1071098736
  3. 4a安全管控 java cas_单点登录与权限管理本质:单点登录介绍
  4. mysql in 索引_关于MySQL种的in函数到底走不走索引、我和同事差点大打出手!
  5. c3p0 服务启动获取连接超时_c3p0获取连接Connection后的Close()---释疑
  6. Fiddler改包场景04——先拦截请求,修改请求,再拦截响应,修改响应,放行响应
  7. 黑马博客——详细步骤(二)项目功能的实现之登录功能
  8. 单元测试框架-Junit
  9. hive 时间函数_Hive常用大法(聚合/排序/分组)
  10. matlab自带SVM算法例子(附函数详解)