一、创建进程的两种方式
#第一种 from multiprocessing import Process import time def task(n): print('我是子进程') time.sleep(n) print('子进程结束') if __name__ == '__main__': # args=(), kwargs={} # t=Process(task,args=(1,)) t = Process(target=task, kwargs={'n': 1}) t.start() # 通知操作系统,开启进程,执行task函数 print('主') #第二种: from multiprocessing import Process import time class Task(Process): def __init__(self, n): super().__init__() self.n = n def run(self): print('我是子进程') time.sleep(self.n) print('子进程结束') if __name__ == '__main__': t = Task(1) # t.run(1) # 不是调用t.run(),而是调用t.start() t.start() print('主')
二、进程间数据相互隔离
#进程之间数据隔离 from multiprocessing import Process import time age = 18 def task(n): global age # 局部修改全局 age = 99 print('我是子进程') time.sleep(n) print('子进程结束') print(age) if __name__ == '__main__': t = Process(target=task, kwargs={'n': 1}) t.start() t.join() # 等待t子进程执行完成 print('主') print(age) # 数据没有变,主进程中打印age和子进程的age没有半毛钱关系,数据是隔离的
三、进程调度
1 先来先服务(对长作业有利,对短作业无益)
2 短作业优先(对短作业有利,对长作业无益)
3 时间片轮转
4 多级反馈队列
四、僵尸进程与孤儿进程
1 僵尸进程:进程结束了,资源还没来得及回收
2 孤儿进程:主进程挂了,子进程还没结束,它就会被专门的进程接管
五、进程对象及其他方法
1 windows:tasklist |findstr 进程id号
2 mac,Linux:ps aux | grep 进程id号
3 进程对象:t=Process(target=task, )或者是在进程内部:current_process()
4 t.pid或者current_process().pid 获取进程id号
5 os.getpid() 同上,获取进程id号
6 os.getppid() 获取父进程id号,子进程中获取父进程id,等于父进程的id号
7 t.is_alive()或者current_process().is_alive() 查看进程是否存活
8 t.terminate() 关闭进程,在主进程关闭
from multiprocessing import Process,current_process import time import os # 每个进程都会有自己的id号pid def task(): print('子进程') # 当前进程的id号 print(current_process().pid) print(os.getpid()) # 跟上面打印出来是一模一样的 # 取出该进程父id号 print('-----',os.getppid()) # current_process()当前进程对象 print(current_process().is_alive()) time.sleep(2) print('子进程结束') if __name__ == '__main__': t = Process(target=task, ) t.start() # t1 = Process(target=task, ) # t1.start() # t.is_alive() # t这个进程是否存活 # print('主进程打印的结果',t.is_alive()) print(t.pid) time.sleep(0.5) # t.terminate() # 把t进程关闭 # time.sleep(0.1) print('主进程打印的结果', t.is_alive())
六、守护进程
from multiprocessing import Process, current_process import time import os def task(): # print(os.getpid()) print('子进程') time.sleep(200) print('子进程结束') if __name__ == '__main__': t = Process(target=task, ) # 守护进程:主进程一旦结束,子进程也结束 # t.daemon=True # 一定要加在启动之前 t.start() time.sleep(1) print('主进程结束') print(os.getppid()) time.sleep(100) # 问题1 :主进程的父进程是谁? 答案:就是pycharm # 问题2 :主进程开了很多子进程,每个都需要设置守护吗? 答案:看你的需求,你想让某个进程是守护:t.daemon=True
七、互斥锁
同时只有一个人能拿到,必须释放,其他人才能再次获取到
from multiprocessing import Process, Lock import json import time import random def search(): # 查票的函数 # 打开文件,读出ticket_count with open('ticket', 'r', encoding='utf-8') as f: dic = json.load(f) print('余票还有:', dic.get('ticket_count')) def buy(): with open('ticket', 'r', encoding='utf-8') as f: dic = json.load(f) time.sleep(random.randint(1, 3)) # 模拟一下网络延迟 if dic.get('ticket_count') > 0: # 能够买票 dic['ticket_count'] -= 1 # 保存到文件中去 with open('ticket', 'w', encoding='utf-8') as f: json.dump(dic, f) print('买票成功') else: # 买票失败 print('买票失败') # 写一个函数,先查票,再买票 def task(mutex): search() # 买票过程要加锁 # 买前加锁 # mutex.acquire() # buy() # 10个进程变成了串行执行 # # 买后释放锁 # mutex.release() with mutex: buy() if __name__ == '__main__': # 锁的创建,在哪?主进程创建锁 mutex = Lock() # 创建一把锁 # 模拟十个人买票(开10个进程) for i in range(10): t = Process(target=task, args=(mutex,)) t.start() # 面向对象高级:魔法方法(__开头的),__enter__和__exit__,上下文管理器 # 自己写一个类,实现类似于打开文件 with open 的功能 # with MyClass('文件名','方式','编码') as f: # f.read() #在这写代码,f就关闭了
接上面问题 补充:
魔法方法之:__inter__ __exit__
class MyClass(): def __init__(self,file_name,mode,encoding): self.file_name=file_name self.mode=mode self.encoding=encoding def __enter__(self): print('只要有with,就会执行我') self.file=open(self.file_name,self.mode,encoding=self.encoding) return self.file def __exit__(self, exc_type, exc_val, exc_tb): # 只要顶格写代码,就会执行我 print('只要顶格写代码,就会执行我') self.file.close() with MyClass('ticket','r','utf-8') as f: print(f.read()) print('xxss') print("sdfadasf") # a=MyClass('ticket','r','utf-8')#这样做不会打印__enter__里的内容
八、队列介绍
from multiprocessing import Queue # 实例化得到要给对象 q=Queue(5) # 默认很大,可以放很多,写了个5,只能放5个 # 往管道中放值 q.put(1) q.put('lqz') q.put(18) q.put(19) # q.put(20) # q.put(21) # q.put_nowait(100) # 从管道中取值 # print(q.get()) # print(q.get()) # print(q.get()) # print(q.get(timeout=100)) # 等0.1s还没有值,就结束 # print(q.get_nowait()) # 不等了,有就是有,没有就没有 print(q.empty()) # 看一下队列是不是空的 print(q.full()) # 看一下队列是不是满的
q=Queue(队列大小)
# 放值
q.put(asdf)
q.put_nowait(asdf) # 队列满了,放不进去就不放了,报错
# 取值
q.get() # 从队列头部取出一个值
q.get_nowait() # 从队列头部取值,没有就抛错
# 队列是否为空,是否满
print(q.empty()) # 看一下队列是不是空的
print(q.full()) # 看一下队列是不是满的
九、IPC机制(进程间通信)
Inter-Process Communication,进程间通信
from multiprocessing import Process, current_process, Queue import time import os def task1(q): print('我是task1进程,我的id号是:%s'%os.getpid()) q.put('lqz is handsome') def task2(q): # res=q.get() # print('我是task2进程,我的id号是:%s'%os.getpid(),res) print('我是task2进程,我的id号是:%s'%os.getpid()) if __name__ == '__main__': q = Queue(5) t1 = Process(target=task1, args=(q,)) t1.start() t2 = Process(target=task2, args=(q,)) t2.start() print(q.get())
---37---