首页 > 编程语言 > 详细

python学习笔记23

时间:2020-04-11 19:52:51      阅读:77      评论:0      收藏:0      [点我收藏+]

python学习笔记23

另一种开启进程的方法

import os
from multiprocessing import Process

class Myprocess(Process):
    def run(self):
        print(os.getpid(),os.getppid())

if __name__==‘__main__‘:
    p = Myprocess()
    p.start

Process类的其他方法和属性

属性:pid(进程序号),name(进程名)

方法:terminate(强制结束子进程。异步非阻塞),is_alive(查看子进程是否存活)

守护进程

import time
from multiprocessing import Process

def func1():
    while True:
        print(‘in func1‘)
        time.sleep(1)

if __name__==‘__main__‘:
    p1 = Process(target=func1)
    p1.daemon() = True # 将p1设置为一个守护进程
    p1.start()
    time.sleep(3)
"""
in func1
in func1
in func1
"""

# 正常情况下,主进程会等待所有的子进程结束(为了回收子进程的资源)
# 而守护进程会等待主进程的代码执行完后结束
# 注意!守护进程不会等待主进程中的其他子进程

当一段程序不想要多个进程同时执行的时候,可以设置一把锁,使得同一时间只有一个进程可以执行。比如12306买票的时候,如果只有1张车票了,但是同时有多个用户买票,那么由于网络延迟的存在会使得多个用户买票成功,这个时候就需要对买票的代码加锁。

# 假设车票的数量num存储在一个叫ticket的json文件中
# 且此时文件中余票数量为1
from multiprocessing import Process
import json
import time

def buy_ticket(i): # 买票
    # 查询余票
    with open(‘ticket‘,mode=‘r‘,encoding=‘utf-8‘) as f:
        ticket = json.load(f)
    time.sleep(0.1) # 模拟网络延时
    if ticket[‘num‘]>0:
        ticket[‘num‘] -= 1
        print(f‘{i}购票成功‘)
    else:
        print("余票不足")
    with open(‘ticket‘,mode=‘w‘,encoding=‘utf-8‘) as f:
        json.dump(ticket,f) # 修改余票信息

if __name__==‘__main__‘:
    # 假设有几个人同时买票
    for i in range(5):
        Process(target=buy_ticket,args=(i,)).start()
"""
0购票成功
1购票成功
2购票成功
3购票成功
4购票成功
"""
# 在余票是1的情况下,五个人同时购票成功,显然这是有缺陷的

所以这时候需要一个程序来控制同一时间进行买票的客户端个数,这个程序就是锁。

# 假设车票的数量num存储在一个叫ticket的json文件中
# 且此时文件中余票数量为1
from multiprocessing import Process
import json
import time

def buy_ticket(i): # 买票
    # 查询余票
    with open(‘ticket‘,mode=‘r‘,encoding=‘utf-8‘) as f:
        ticket = json.load(f)
    time.sleep(0.1) # 模拟网络延时
    if ticket[‘num‘]>0:
        ticket[‘num‘] -= 1
        print(f‘{i}购票成功‘)
    else:
        print("余票不足")
    with open(‘ticket‘,mode=‘w‘,encoding=‘utf-8‘) as f:
        json.dump(ticket,f) # 修改余票信息
def get_ticket(i,lock):
    lock.acquire() # 拿到钥匙
    buy_ticket(i)
    lock.release() # 归还钥匙
if __name__==‘__main__‘:
    # 假设有几个人同时买票
    # 设置锁
    lock = Lock()
    for i in range(5):
        Process(target=get_ticket,args=(i,lock)).start()
"""
0购票成功
余票不足
余票不足
余票不足
余票不足
"""

这里锁的作用是控制lock.acquire()lock.release()之间的代码同一时间只有一个进程执行。它的作用机制是将之间的代码上锁,同时钥匙也在旁边但是只有一把。同一时间只能一个进程拿钥匙开锁进入并关门,直到执行完再出门上锁还钥匙,这样就保证了同一时间只能一个进程执行。

# 上面代码中的上锁过程需要作如下优化
"""
lock.acquire() # 拿到钥匙
buy_ticket(i)
lock.release() # 归还钥匙
"""
# 修改为:
with lock:
    buy_ticket(i)
# 因为如果buy_ticket(i)执行过程中程序报错,那么会因为没有执行release这个归还钥匙的代码而导致钥匙丢失
# 而使用with则能够克服这个异常情况

使用锁的时候,没有被锁住的代码仍然会被进程并发执行。上述这种锁称为互斥锁,在同一个进程中不能acquire多次,因为钥匙只有一把,只有第一个acquire会被执行。

队列和生产者消费者模型

进程之间的相互通信(IPC,Inter Process Communication)

  • 基于文件:同一台机器上的多个进程之间通信

    • Queue(队列):基于socket的文件级别的通信来完成数据传递
    # 父进程和子进程之间通信
    from multiprocessing import Queue,Process
    
    def func(q):
        q.put(‘hello‘)
    
    if __name__==‘__main__‘:
        q = Queue() # 只有队列可以做到传输,其他的数据类型都不行
        p = Process(target=func,args=(q,)) # 子进程传输消息
        p.start()
        print(q.get()) # 父进程尝试接收
    # hello
    
  • 基于网络:同一台机器或多台机器上的多进程通信

    • 第三方工具(消息中间件):memcache、redis、rabbitmq、kafka

生产者消费者模型

本质:让生产数据和消费数据的效率达到平衡并且最大化的模型。

# 写一个最最简单的生产者消费者模型
from multiprocessing import Process

def consumer(q): # 消费者:通常取到数据后还要对数据进行处理
    for i in range(5):
        print(q.get())

def producer(q): # 生产者:通常在传数据之前要通过某些代码获取数据
    for i in range(5):
        q.put(i)
     
if __name__==‘__main__‘:
    q = Queue()
    c1 = Process(target=consumer,args=(q,))
    p1 = Process(target=producer,args=(q,))
    c1.start()
    p1.start()
"""
0
1
2
3
4
"""

python学习笔记23

原文:https://www.cnblogs.com/20-03-14/p/12680690.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!