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的布尔值的变化实现了进程间的通信。

 

posted @ 2019-03-09 20:18  妇愁者  阅读(217)  评论(0编辑  收藏  举报