zoukankan      html  css  js  c++  java
  • python多进程

    首先进程是资源调度的一个最小集合,通常起一个进程,然后通过操作系统完成资源的调度。具体的细节还需要进修。。。。。

    总之,通过python也可以实现多进程的。

    通常,我们启动一个进程的时候,都是通过父进程来启动这个对应的子进程,在python中,我们可以通过os模块,通过os.getpid()&os.getppid()来查看当前进程以及父进程的进程ID。或者我们可以通过multiprocessing模块中的创建一个进程的实例化对象后,通过调用pid这个方法来查看这个进程的进程ID。

    当我们利用多进程的时候,就可以实现同一时间内做多件事情。在python中,如果我们启动多个子进程,主进程的执行和子进程的执行是没有影响的,但是,如果你想实现等待子进程执行完毕后才允许主进程执行完毕,可以利用join()方法,这里的join就相当于wait,就是,等待这个进程执行完毕,才进行下一步。   同样,当主进程执行完毕后,程序并不会退出,而是等待子进程也执行完毕才会退出,这时候,如果我们想实现主进程执行完毕后,某些子进程必须跟随者主进程的结束而结束,就可以设置某个子进程p,令其p.daemon = True,使这个进程变成守护进程,这样,当主进程执行完毕后,守护进程便会跟着退出(不管它执行完毕与否)。  更直白一点,就像古代皇帝死后,一些妃子需要陪葬,大臣不需要陪葬,这时候,这些妃子就相当于守护进程。。。

    插入一段代码。。研究一下。

    from multiprocessing import Process
    import time
    
    def func():
        time.sleep(5)
        print('^^'*5)
    
    def run():
        time.sleep(1)
        print('i am running')
    
    if __name__ == '__main__':
        p1 = Process(target=run)
        p1.daemon = True
    
        p1.start()
        p2 = Process(target=func)
        p2.start()
        print(p2.pid)
        for i in range(5):
            time.sleep(0.1)
            print('i am chief process')

    除了这些之外,多进程还有某些特性。假设你要实现一个抢票功能,这时候,你想着so easy,每个人抢票的行为作为一个进程,不就可以实现同时抢票了吗?于是开始bangbangbang敲好了代码,测试的时候发现为什么只放出去一张票,好几个人抢到了,这是因为,起多个进程,他们有可能同时读入这个数据,导致疯狂被投诉。。。这时候,不要慌,进程里面还有进程锁这个东西,什么意思呢,就是好比你去拉屎,拉屎的时候肯定只能一人一个坑位,你进去了把门锁住,防止别人进来(除非你不是在拉屎,里面有俩人。。咳咳)。进程所就是,你要获取这个数据,你刚刚得到这个数据要进行处理,这个时候,你就把门反锁住,等你处理完了再把门打开,钥匙挂到门上,这样就避免了bug。 如果你说,一次只能进一个人这样太不友好了,我就是喜欢群P,怎么办?你可以在门上挂多点钥匙啊,这样不就可以好多人进去,限制了进去的人的数量。。。。这种可以有多个钥匙的锁称为“信号量”(semaphore)。

    给你一个抢票的游戏:

    from multiprocessing import Process
    from multiprocessing import Lock
    import time
    import random
    import json
    
    def search_ticket():
        with open('ticket') as f:
            ticket = (json.load(f)['count'])
            print('there is %s tickets'%ticket)
            return ticket
    def get_ticket(i,lock):
        count_ticket = search_ticket()
        lock.acquire()
        if count_ticket:
            print('%s has gotten a ticket'%i)
            count_ticket -= 1
            with open('ticket','w') as f:
                json.dump({'count':count_ticket},f)
        else:
            print('there is no ticket')
        lock.release()
    if __name__ == "__main__":
        lock = Lock()
        for i in range(10):
            time.sleep(random.randint(0,1))
            p = Process(target=get_ticket,args=(i,lock))
            p.start()

    这里用json文件代表抢票的数据库,插入random和time模块模拟实际抢票过程中的网络时延。

    接下来用信号量来模拟一下拉屎这个环节,每个人都有0-3秒的时间,毕竟超过三秒都是病。。。

    from multiprocessing import Process
    from multiprocessing import Semaphore
    import time
    import random
    def toilet(i,sem):
        sem.acquire()
        print('%s 进去拉屎了'%i)
        time.sleep(random.randint(0,3))
        sem.release()
        print('%s 已经拉完出来了,很饱'%i)
    
    if __name__ == '__main__':
        sem = Semaphore(4)
        for i in range(10):
            p = Process(target=toilet,args=(i,sem))
            p.start()

    除了锁这个概念外,进程还有一些小知识点需要掌握,队列和事件。队列很简单,无非就是先进先出,进去出去的原则,除此之外,还有qsize这个用法,但是再多进程中,这个方法有可能不准确,因为如果你读取一个数据的size的同时,又put进去了一个数据,通过队列可以实现子进程和主进程以及子进程和子进程之间的通信。

    事件的话,就是可以模拟红绿灯,Event只需要记住这几个就行,clear/set/wait/is_set,当is_set为True的时候,程序是不阻塞的,默认情况下,wait是阻塞的,这样说也不大明白,还是插入一段红绿灯的例子:

    from multiprocessing import Event
    from multiprocessing import Process
    import time
    
    def traffic_light(e):
        while True:
            if e.is_set():
                print('绿灯,可以通过')
                time.sleep(2)
                e.clear()
            else:
                print('红灯,不能通过')
                time.sleep(3)
                e.set()
    def car(i,e):
        e.wait()
        print('%s 车可以通过'%i)
    
    
    if __name__ == '__main__':
        e = Event()
        p1 = Process(target=traffic_light,args=(e,))
        p1.start()
        for i in range(20):
            if i % 3 == 0:
                time.sleep(3)
            else:
                p = Process(target=car,args=(i,e))
                p.start()

    此例中,假设车流量比较小,每三秒过来两辆车,红绿灯启用一个进程,每辆车也视为一个进程,通过事件e的is_set的布尔值的变化实现了进程间的通信。

  • 相关阅读:
    使用vue-cli搭建SPA项目
    NodeJS的环境搭建+传统ELmentui+vue开发
    vue路由
    Vue基础语法(样式绑定,事件处理,表单,Vue组件)
    动态规划 | 保留重复元素的LCS 1045
    动态规划 | 1007 最大连续子序列和
    数学问题 | 质因数分解:1096
    数学问题 | 连续质因数分解:1096
    数据结构 | 哈希表二次探查法 : 1078
    数学问题 | 1015 进制转换与素数问题
  • 原文地址:https://www.cnblogs.com/zz1314/p/10497157.html
Copyright © 2011-2022 走看看