pycharm激活码网站:http://idea.medeming.com/jets/
一台计算机上面运行着很多进程,那么计算机是如何区分并管理这些进程的呢?
# 计算机会给每一个运行的进程分配一个PID号(PID号(进程号):也是唯一的)
# 如何查看?
1. window电脑,加入cmd,输入tasklist,然后回车,即可查看当前计算机上面所有运行的进程
2. mac电脑,输入ps -aux,然后回车,即可查看当前计算机上面所有运行的进程
# 如何在这么多进程号里查到自己想要的那个进程号呢?
1. window系统:tasklist|findstr 进程号
2. mac系统:ps -aux|grep 进程号
1 import os 2 import time 3 from multiprocessing import Process, current_process 4 5 6 def task(): 7 print( 8 '%s is running' % current_process().pid) # 使用from multiprocessing import Process, current_process,查看当前进程的PID进程号 9 print('%s is running' % os.getpid()) # 使用os获取当前进程号 10 print(f'{os.getppid()}子进程的主进程号') # 查看当前进程的父进程进程号 11 time.sleep(3) 12 13 14 if __name__ == '__main__': 15 p = Process(target=task) 16 p.start() 17 print('主', current_process().pid) 18 print('主进程', os.getpid()) 19 p.terminate() # 杀手当前进程 20 time.sleep(0.2) # 给系统时间去杀死当前进程,这时候下面代码才为False 21 print(p.is_alive()) # True,判断当前进程是否存活,p.terminate()并不是立马杀死,是告诉操作系统去帮你杀死当前进程,需要时间去杀死 22 ''' 23 一般情况下我们会默认将存储布尔值的变量名和返回的结果是布尔值的方法名,都起以成is——开头 24 ''' 25 # 如何在这么多进程号里查到自己想要的那个进程号呢? 26 # window系统:tasklist|findstr 进程号 27 # mac系统:ps -aux|grep 进程号
。
。
【僵尸进程与孤儿进程】
1 import time 2 from multiprocessing import Process 3 4 5 def run(): 6 print('hello world') 7 time.sleep(3) 8 print('get out') 9 10 11 if __name__ == '__main__': 12 p = Process(target=run) 13 p.start() 14 print('主') # 主、 hello world、 get out 15 16 17 僵尸进程:进程执行完毕后并不会立刻销毁所有的数据 会有一些信息短暂保留下来 18 比如进程号、进程执行时间、进程消耗功率等给父进程查看 19 所有的进程都会变成僵尸进程 20 什么时候回收子进程占用的pid号? 21 父进程等待子进程运行结束,父进程调用join方法 22 23 24 孤儿进程 25 子进程正常运行 父进程意外死亡 操作系统针对孤儿进程会派遣福利院管理
。
。
【守护进程】
1 把项目进程做成某一个进程的守护进程,这样即使项目因为意外原因挂掉, 2 主进程只要不挂监测到后,又会将项目进程再起起来 3 4 5 会随着主进程的结束,守护进程立刻结束!!! 6 7 8 使用场景: 9 写了一个多进程的python代码,把所有的子进程设成主进程的守护进程 10 这样主进程一关,所有设成守护进程的子进程也全部关闭了,这样节省计算机效率了!!! 11 需要做批量管理,一键关闭所有的进程,就可以把所有的子进程设成主进程的守护进程 12 13 import time 14 from multiprocessing import Process 15 16 17 def task(name): 18 print('%s总管正在活着' % name) 19 time.sleep(3) 20 print('%s总管正在死了' % name) 21 22 23 if __name__ == '__main__': 24 p = Process(target=task, args=('alex',)) 25 p.daemon = True # 将进程p设置为守护进程,必须在start()方法调用之前设置,否则会报错 26 p.start() 27 print('皇帝egon寿终正寝')
PS:守护进程关键字: daemon
。
。
【互斥锁,模拟抢票】
1 mutex:互斥锁 2 Only one task may hold the mutex at a time, and only this task can unlock the mutex. 3 一次只能有一个任务持有互斥锁,并且只有这个任务可以解锁互斥锁。 4 ----------------------------------------- 5 互斥锁的作用:将并发变成串行,牺牲了效率,但是保证了数据的安全!! 6 7 互斥锁:锁不能滥用,建议只加在操作数据的部分,否则整个程序的效率会极低!! 8 ------------------------------------------------------------------------------- 9 10 还是就模拟文件里面只有一张票的情况:{"ticket_num":1} 11 =============================================== 12 模拟抢票 13 14 # 模拟抢票功能 15 from multiprocessing import Process, Lock 16 import json 17 import time 18 import random 19 20 21 # 查票 22 def search(i): 23 # 文件操作读取票数 24 with open(r'C:\Users\靳小洁\PycharmProjects\pythonProject\Day39\data.json', 'r', encoding='utf-8') as f: 25 dic = json.load(f) 26 print('用户%s查询到剩余票数:%s' % (i, dic.get('ticket_num'))) 27 28 29 # 买票 1.先查 2.再买 30 def buy(i): 31 with open(r'C:\Users\靳小洁\PycharmProjects\pythonProject\Day39\data.json', 'r', encoding='utf-8') as f: 32 dic = json.load(f) 33 # 模拟网络延迟 34 time.sleep(random.randint(1, 3)) 35 # 判断当前是否有票 36 if dic.get('ticket_num') > 0: 37 # 修改数据库 买票 38 dic['ticket_num'] -= 1 39 # 写入数据库 40 with open(r'C:\Users\靳小洁\PycharmProjects\pythonProject\Day39\data.json', 'w', encoding='utf-8') as f: 41 json.dump(dic, f) 42 print('用户%s买到票' % i) 43 else: 44 print('用户%s没有买到票' % i) 45 46 47 # 整合上面两个函数,每个人都查票买票 48 def run(i): 49 # 查票 50 search(i) 51 buy(i) 52 53 54 # 模拟多个人买票 55 if __name__ == '__main__': 56 for i in range(1, 11): 57 p = Process(target=run, args=(i,)) 58 p.start() 59 60 这时候发现10个人都查看到了余票且都买到了票,但是票只有一张,显然是错误的 61 62 63 =============================================== 64 这时候我们就用到了锁---互斥锁Lock 65 66 67 # 模拟抢票功能 68 from multiprocessing import Process, Lock 69 import json 70 import time 71 import random 72 73 74 # 查票 75 def search(i): 76 # 文件操作读取票数 77 with open(r'C:\Users\靳小洁\PycharmProjects\pythonProject\Day39\data.json', 'r', encoding='utf-8') as f: 78 dic = json.load(f) 79 print('用户%s查询到剩余票数:%s' % (i, dic.get('ticket_num'))) 80 81 82 # 买票 1.先查 2.再买 83 def buy(i): 84 with open(r'C:\Users\靳小洁\PycharmProjects\pythonProject\Day39\data.json', 'r', encoding='utf-8') as f: 85 dic = json.load(f) 86 # 模拟网络延迟 87 time.sleep(random.randint(1, 3)) 88 # 判断当前是否有票 89 if dic.get('ticket_num') > 0: 90 # 修改数据库 买票 91 dic['ticket_num'] -= 1 92 # 写入数据库 93 with open(r'C:\Users\靳小洁\PycharmProjects\pythonProject\Day39\data.json', 'w', encoding='utf-8') as f: 94 json.dump(dic, f) 95 print('用户%s买到票' % i) 96 else: 97 print('用户%s没有买到票' % i) 98 99 100 # 整合上面两个函数,每个人都查票买票 101 def run(i, mutex): 102 # 查票 103 search(i) 104 # 买票,给它加锁处理 105 # 抢锁 106 mutex.acquire() 107 buy(i) 108 # 释放锁 109 mutex.release() 110 111 112 # 模拟多个人买票 113 if __name__ == '__main__': 114 # 在主进程中创建一个锁对象,让所有的子进程抢 115 mutex = Lock() 116 for i in range(1, 11): 117 p = Process(target=run, args=(i, mutex)) 118 p.start()
。
。
【队列】
什么是队列:进程间通信:队列模块(Queue)
队列:先进先出
堆栈:先进后出
1 # 进程间通信:队列模块(Queue) 2 from multiprocessing import Queue 3 4 # 创建一个队列 5 q = Queue(4) # ()可以传数字,表示生成的队列最大可以同时存放的数据量 6 # 往队列中存数据 7 q.put(111) 8 q.put(222) 9 q.put(333) 10 q.put(444) 11 # q.put(555) # 队列满了,put会阻塞,直到有位置让出来,才不会阻塞 12 print(q.full()) # 判断队列是否满了 13 print(q.empty()) # 判断队列是否为空 14 15 # print(q.full()) # 判断队列是否满了 16 17 # 从队列中取数据 18 v1 = q.get() 19 v2 = q.get() 20 v3 = q.get() 21 v4 = q.get() 22 # v5 = q.get() 23 v5 = q.get_nowwait() # 没有数据直接报错 24 # v6=q.get(timeout=3) # 没有数据的话,等待3秒,还是没有的话,报错 25 print(v1, v2, v3, v4, v5) # 队列中如果已经没有数据的话,get取不到会阻塞 26 27 # ==============总结 28 ''' 29 q.full() 30 q.empty() 31 q.get_nowait() 32 这三种方法再多进程的情况下是不精确的 33 '''
。
。
IPC机制进程间通信
1 问题引入: 2 1.什么是进程间通信(Inter-Process Communication, IPC) 3 4 进程间通信(Inter-Process Communication, IPC)是指两个或多个进程之间进行信息交换的过程。 5 6 它是一种计算机编程技术,用于在不同进程之间共享数据和资源。 7 8 2.那如何实现进程间通信? 9 10 借助于消息队列,进程可以将消息放入队列中,然后由另一个进程从队列中取出。 11 这种通信方式是非阻塞的,即发送进程不需要等待接收进程的响应即可继续执行。 12 multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的 13 14 管道:subprocess (stdin stdout stderr) 15 stdin、stdout和stderr是Python中的三个内置文件对象,它们分别代表标准输入、标准输出和标准错误。这些对象也可以作为管道使用。
进程间通信有两种情况:
1.主进程跟子进程借助于队列通信
1 from multiprocessing import Process, Queue 2 3 4 def producer(q): 5 q.put('我是小宝贝') 6 print('hello big baby') 7 8 9 if __name__ == '__main__': 10 q = Queue() 11 p = Process(target=producer, args=(q,)) 12 p.start() 13 print(q.get()) # 先hell,再我是
2.子进程跟子进程借助队列通信
1 from multiprocessing import Process, Queue 2 3 4 def producer(q): 5 q.put('子进程添加的数据') 6 7 8 def consumer(q): 9 print('子进程获取队列中的数据', q.get()) 10 11 12 if __name__ == '__main__': 13 q = Queue() 14 p = Process(target=producer, args=(q,)) 15 p1 = Process(target=consumer, args=(q,)) 16 p.start() 17 p1.start() 18 print(q.get()) # 获取子进程添加的数据
。
。
【生产者消费者模型】
生产者(爬取数据的代码)
负责产生数据的'人'
消费者(正则筛选数据的代码)
负责处理数据的'人'
-------------------------------------
该模型除了有生产者和消费者之外
还必须有消息队列(只要是能够提供数据保存服务和提取服务的理论上都可以)!!!
一般情况下:生产出来的数据,消费者要消费的数据,生产者与消费者之间不是直接关联的!!!
这样生产者与消费者都不用等待彼此了!!!!!!
有了消息队列的存在就可以实现生产者与消费者之间的解耦合,也就是可以不同时出现!!!
1 import time 2 import random 3 from multiprocessing import Process, Queue, JoinableQueue 4 5 6 # 生产者 7 def producer(name, food, q): 8 for i in range(5): 9 data = "%s生产了%s%s" % (name, food, i) 10 # 模拟延迟 11 time.sleep(random.randint(1, 3)) 12 print(data) 13 # 生产者生产数据,放入队列 14 q.put(data) 15 16 17 # 消费者 18 def consumer(name, q): 19 # 消费者光盘行动 20 while True: 21 food = q.get() # 没有数据就会卡住 22 # 判断当前是否有结束的标识 23 # if food is None: break 24 time.sleep(random.randint(1, 3)) 25 print('%s 吃 %s' % (name, food)) 26 q.task_done() # 计数-1,表示当前任务完成,q = JoinableQueue() 27 28 29 if __name__ == '__main__': 30 # q = Queue() 31 q = JoinableQueue() 32 p1 = Process(target=producer, args=('jh', '包子', q)) 33 p2 = Process(target=producer, args=('wxx', '油条', q)) 34 c1 = Process(target=consumer, args=('cxx', q)) 35 c2 = Process(target=consumer, args=('lxx', q)) 36 p1.start() 37 p2.start() 38 # 将消费者设置成守护进程,主进程结束后,消费者进程也结束,解决q.join()问题 39 c1.daemon = True 40 c2.daemon = True 41 c1.start() 42 c2.start() 43 # ========================这时候运行出现问题(food = q.get()问题所在):消费者吃完以后,生产者还在生产,导致程序卡死(键卡在那里) 44 p1.join() 45 p2.join() 46 # ========等待生产者生产完毕以后,往队列中添加特定的结束符号 47 # q.put(None) 48 # q.put(None) # 这时候程序正常结束,None有几个,取决于生产者生产几个 49 q.join() # 等待队列中的所有数据被消费以后,再执行往下执行代码,q = JoinableQueue() 50 51 ''' 52 JoinableQueue() 当往该队列中存入数据的时候,内部会有一个计数器+1 53 每当调用task_done()的时候,计数器-1 54 q.join()当计数器为0的时候,代表生产者生产的数据,都被消费者消费完毕了,q.join()往下执行 55 ''' 56 # 只要q.join()执行完毕,说明消费者已经处理完数据了,消费者就没有存在的必要了