python进程学习
Posted grave-seven
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python进程学习相关的知识,希望对你有一定的参考价值。
学习知识点:
1.知识点叫什么
2.知识点用在哪
3.知识如何实现
一. 进程
1.进程是什么
进程是cpu分配资源的最小单位
理解:在QQ这个进程里,传输一段文字开启一个线程,传输语音又开启一个线程。所以运行某个软件相当于开启了一个进程。而在这个进程里,有多个功能来支持QQ正常运行,这些功能又各自占了一条线程。
一个进程管理着多个线程。(一个进程至少带一个线程)
线程和进程的:
1.单进程单线程:一个人在一个桌子上吃饭
2.单进程多线程:多个人在一个桌子上吃饭
3.多进程单线程:多个人每个人在自己桌子上吃饭
2.进程的状态
状态分析:就绪态(运行的条件都已经慢去)执行态(zpu正在执行其他的功能)等待态(等待某些条件满足,例如一个程序sleep了,此时就处于等待态)
3.进程的作用
实现多个任务同时运行,跟多线程功能基本一致。
1 import multiprocessing # 导包 2 import time 3 4 5 def test1(): 6 while True: 7 print("1------") 8 time.sleep(1) 9 10 11 def test2(): 12 while True: 13 print("2------") 14 time.sleep(1) 15 16 17 def main(): 18 # 创建进程,跟创建多线程一致 19 t1 = multiprocessing.Process(target=test1) 20 t2 = multiprocessing.Process(target=test2) 21 22 # 开启进程 23 t1.start() 24 t2.start() 25 26 27 if __name__ == ‘__main__‘: 28 main()
4.主进程与子进程
子进程开启会复制主进程一样的代码
5.进程和线程的区别
1.进程浪费资源较大,而且一段代码进程执行的速度明显比线程慢。
2.进程的资源相互独立不共享,如需通信需要借助一些方法。 线程资源是共享的,但是也有bug,需要加锁。
3.进程稳定性好,一个任务挂了,有可能整个进程都挂了,但不会影响其他进程。
二. 进程命令进程
1.查看进程
ps -aux
htop
top
2.杀死进程
kill pid名 kill -9 pid名
关于这个命令,之前询问别人其之间的区别,有人讲kill -9 pid 是删除所有与进程相关的,我的疑惑就来了,既然进程之间不相互影响,那么删的是什么相关的呢?一个杀死进程的命令,除了进程还能杀死什么?
于是,我上网查了下,再别人的博客下得到了答案:一般不建议使用 kill -9 pid
kill(默认是-15)的真实含义是, 向进程发送信息,而不是杀死进程。 kill 1234 是向进程1234发送一个SIGTERM信号,有时候 kill 1234 并不能结束这个进程,用kill -9 1234 是真的kill了, kill -9 1234是向1234发送SIGKILL信号
两句命令的区别:SIGNKILL(9) 的效果是立即杀死进程. 该信号不能被阻塞, 处理和忽略。 SIGNTERM(15) 的效果是正常退出进程,退出前可以被阻塞或回调处理。并且它是Linux缺省的程序中断信号。
一句话, kill是温柔地杀, kill -9是霸气地杀
三. 进程的相关知识
1.pid获取
1 import multiprocessing 2 import time 3 import os 4 5 6 def test1(): 7 while True: 8 print("1-----") 9 time.sleep(1) 10 print("子进程1",os.getpid()) # 获取当前进程号 11 print("主进程",os.getppid()) # 获取主进程的进程号 12 13 14 def test2(): 15 while True: 16 print("2-----") 17 time.sleep(1) 18 print("子进程2",os.getpid()) 19 print("主进程",os.getppid()) 20 21 22 def main(): 23 # 创建进程 24 t1 = multiprocessing.Process(target=test1) 25 t2 = multiprocessing.Process(target=test2) 26 27 # 开启进程 28 t1.start() 29 t2.start() 30 31 print("主进程", os.getpid()) # 获取主进程的进程号 32 33 34 if __name__ == ‘__main__‘: 35 main()
主进程 7904 1----- 2----- 子进程1 7560 主进程 7904 1----- 子进程2 6136 主进程 7904 2----- 子进程1 7560 主进程 7904 1----- 子进程2 6136 主进程 7904 2----- 子进程1 7560
2.子进程中不能使用input()函数,主进程会等到子进程结束而结束,线程是用来执行代码的,进程使用分配资源的,子进程会复制主进程的资源数据,进程之间的数据不共享,进程的执行时无序的。
3.传参
四. 进程与线程的对比
1.进程是分配资源的单位,线程是程序调度的单位
2.进程运行必定有一个主线程运行
3.全局变量:线程共享全局变量,进程不共享全局变量。
4.加深理解进程与线程的图片
创建
五. 进程间的通讯
1.使用的技术:Queue队列
2.作用:让进程之间可以通讯
import queue # 先进先出 q = queue.Queue() q.put(‘1‘) q.put(‘2‘) q.put(‘3‘) print(q.get()) print(q.get()) print(q.get()) # 后进先出 q = queue.LifoQueue() q.put(‘1‘) q.put(‘2‘) q.put(‘3‘) print(q.get()) print(q.get()) print(q.get()) # 存储数据时可设置优先级的队列 q = queue.PriorityQueue() # put进入一个元祖,元祖的第一个元素是优先级,数字越小优先级越高 q.put((20, ‘a‘)) q.put((10, ‘b‘)) q.put((30, ‘c‘)) print(q.get()) print(q.get()) print(q.get())
3.使用方式
创建队列放入数据
获取数据
# 定义一个队列 import multiprocessing # 定义一个队列 # 队列的作用存取数据 # 队列中的数据取完就没了 # 队列中先存先取 import time queue = multiprocessing.Queue(3) # 存数据 queue.put_nowait("abc") queue.put_nowait("abc") queue.put_nowait("abc") # queue.put_nowait("abc") # print(queue.empty()) # 空是有bug time.sleep(1) # 取 print(queue.get_nowait()) print(queue.get_nowait()) # print(queue.get_nowait()) print(queue.empty()) # 空是有bug # print(queue.get_nowait())
4.案例:一个进程读一个进程写,在进程创建前创建进程队列
import multiprocessing import queue import time def write(queue): # 记得传参数 """写数据的函数""" # 通过循环去写数据 for temp in range(10): queue.put(temp) print(temp) time.sleep(1) def read(queue): """定义一个读的函数""" data_list = [] # 通过循环去读数据 while True: if queue.empty(): break data_list.append(queue.get()) print(data_list) def main(): # 定义一个进程队列 queue = multiprocessing.Queue() # 这个说明没有限制机器性能 # 创建两个进程 process_write = multiprocessing.Process(target=write, args=(queue,)) process_read = multiprocessing.Process(target=read, args=(queue,)) # 开启线程 process_write.start() process_write.join() # 控制写完读,保证有数据在读 process_read.start() if __name__ == ‘__main__‘: main()
打印结果:先顺序打印0-9 ,停顿1S,在打印0-9的列表。 0 1 2 3 4 5 6 7 8 9 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
六. 进程池
1.什么是进程池
python中,进程池内部会维护一个进程序列。当需要时,程序会去进程池中获取一个进程。
如果进程池序列中没有可供使用的进程,那么程序就会等待,直到进程池中有可用进程为止
理解:一个学校有很多教室,不同的班级轮流使用这些教室
内置的一些方法:
apply 从进程池里取一个进程并同步执行
apply_async 从进程池里取出一个进程并异步执行
terminate 立刻关闭进程池
join 主进程等待所有子进程执行完毕,必须在close或terminete之后
close 等待所有进程结束才关闭线程池
2.进程池的作用
用来重复利用进程,节省资源
3.同步执行:放个代码感受一下,创建3个进程,循环执行5次任务,这时三个进程轮流执行这5个任务,问题来了,这三个进程号是不变的,也就是创建几个进程池里数字为几,最多就可以创建几个进程,不可不填。感受代码。
同步的特点:一个一个执行我们的任务
1 from multiprocessing import Pool 2 import time 3 import os 4 5 6 def func(): 7 time.sleep(1) 8 print("run",os.getpid()) # 获取当前进程号 9 10 11 def main(): 12 p1 = Pool(3) # 设定开启3个进程池 13 for i in range(5): 14 p1.apply(func) # 设定异步执行任务 15 16 17 if __name__ == ‘__main__‘: 18 main()
打印结果: run 7996 run 9560 run 4184 run 7996 run 9560
4.异步执行:所有进程同时执行任务 ,apply_async必须和close()必须和join() 这三个必须一起使用,join()要放在for循环之外
1 from multiprocessing import Pool 2 import time 3 import os 4 5 6 def func(): 7 time.sleep(1) 8 print("run",os.getpid()) 9 10 11 def main(): 12 p1 = Pool(3) # 设定开启3个进程池 13 for i in range(5): 14 p1.apply_async(func) # 异步,有问题,必须加入join跟close 15 16 p1.close() # 关闭进程池,不在接收新的任务 17 p1.join() # 让我们的主进程等待进程池完成再结束 18 19 20 if __name__ == ‘__main__‘: 21 main()
打印结果: 前三行同时出现,停顿1S,后面两行同时出现 run 10512 run 12788 run 1688 run 10512 run 12788
案例:复制文件夹
链接:http://blog.csdn.net/chaipp0607/article/details/60779129
并发:看上去像同时发生的,指应用能够交替执行不同的任务,注意点,能够处理多个任务,没说非要同时。
并行:指应用能够同时执行不同的任务,注意点,必须同时。
两者区别:一个是交替执行,一个是同时执行。
以上是关于python进程学习的主要内容,如果未能解决你的问题,请参考以下文章