python--进程

一、进程、程序

  1.编写完成的代码,在没有运行的时候,称之为程序

  2.正在运行着代码,称之为进程

二、用fork创建进程

import os

res = os.fork()
if res == 0:
    while True:
        print('111111')
        time.sleep(1)
else:
    while True:
        print('22222')
        time.sleep(1)

#结果为:
111111
22222

111111
22222
使用fork创建多进程(多任务)

  1.os.getpid():获取当前进程id

  2.os.getppid():获取父进程的id

三、一些知识点

  1.全局变量在多个进程间不共享

四、process创建子进程

from multiprocessing import Process

def test():
    pass

p = Process(target=test)
p.start()    #让这个进程开始执行test里面的代码
创建子进程

  1.用process创建的子进程,在子进程结束之后主进程才会结束

  2.p.join([timeout])  堵塞,在子进程执行完毕后再执行其后的代码,timeout代表超时时间表示等待的时间

  3.p.terminate()立即结束子进程

  4.process子类创建子进程

from multiprocessing import Process
import time
import os

#继承Process类
class Process_Class(Process):
    #因为Process类本身也有__init__方法,这个子类相当于重写了这个方法,
    #但这样就会带来一个问题,我们并没有完全的初始化一个Process类,所以就不能使用从这个类继承的一些方法和属性,
    #最好的方法就是将继承类本身传递给Process.__init__方法,完成这些初始化操作
    def __init__(self,interval):
        Process.__init__(self)
        self.interval = interval

    #重写了Process类的run()方法
    def run(self):
        print("子进程(%s) 开始执行,父进程为(%s)"%(os.getpid(),os.getppid()))
        t_start = time.time()
        time.sleep(self.interval)
        t_stop = time.time()
        print("(%s)执行结束,耗时%0.2f秒"%(os.getpid(),t_stop-t_start))

if __name__=="__main__":
    t_start = time.time()
    print("当前程序进程(%s)"%os.getpid())        
    p1 = Process_Class(2)
    #对一个不包含target属性的Process类执行start()方法,就会运行这个类中的run()方法,所以这里会执行p1.run()
    p1.start()
    p1.join()
    t_stop = time.time()
    print("(%s)执行结束,耗时%0.2f"%(os.getpid(),t_stop-t_start))
process子类创建子进程

五、使用进程池创建子进程pool

  1.当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态成生多个进程,但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法。初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来执行

from multiprocessing import Pool
import os,time,random

def worker(msg):
    t_start = time.time()
    print("%s开始执行,进程号为%d"%(msg,os.getpid()))
    #random.random()随机生成0~1之间的浮点数
    time.sleep(random.random()*2) 
    t_stop = time.time()
    print(msg,"执行完毕,耗时%0.2f"%(t_stop-t_start))

po=Pool(3) #定义一个进程池,最大进程数3
for i in range(0,10):
    #Pool.apply_async(要调用的目标,(传递给目标的参数元祖,))
    #每次循环将会用空闲出来的子进程去调用目标
    po.apply_async(worker,(i,))

print("----start----")
po.close() #关闭进程池,关闭后po不再接收新的请求
po.join() #等待po中所有子进程执行完成,必须放在close语句之后
print("-----end-----")

#结果
----start----
0开始执行,进程号为21466
1开始执行,进程号为21468
2开始执行,进程号为21467
0 执行完毕,耗时1.01
3开始执行,进程号为21466
2 执行完毕,耗时1.24
4开始执行,进程号为21467
3 执行完毕,耗时0.56
5开始执行,进程号为21466
1 执行完毕,耗时1.68
6开始执行,进程号为21468
4 执行完毕,耗时0.67
7开始执行,进程号为21467
5 执行完毕,耗时0.83
8开始执行,进程号为21466
6 执行完毕,耗时0.75
9开始执行,进程号为21468
7 执行完毕,耗时1.03
8 执行完毕,耗时1.05
9 执行完毕,耗时1.69
-----end-----
进程池

  2.apply_async(非阻塞式)  apply(阻塞式):必须等上一个任务执行完成后才能执行下一个

  3.进程池中的异步

from multiprocessing import Pool
import time
import os

def test():
    print("---进程池中的进程---pid=%d,ppid=%d--"%(os.getpid(),os.getppid()))
    for i in range(3):
        print("----%d---"%i)
        time.sleep(1)
    return "hahah"

def test2(args):
    print("---callback func--pid=%d"%os.getpid())
    print("---callback func--args=%s"%args)

pool = Pool(3)
pool.apply_async(func=test,callback=test2)

time.sleep(5)

print("----主进程-pid=%d----"%os.getpid())
进程池中的异步

六、使用queue完成进程间通信

  1.queue队列的导入:from multiprocessing import queue

  2.实例化queue:q = Queue(int),初始化Queue()对象时(例如:q=Queue()),若括号中没有指定最大可接收的消息数量,或数量为负值,那么就代表可接受的消息数量没有上限(直到内存的尽头)

  3.Queue.qsize():返回当前队列包含的消息数量;

  4.Queue.empty():如果队列为空,返回True,反之False

  5.Queue.full():如果队列满了,返回True,反之False

  6.Queue.get([block[, timeout]]):获取队列中的一条消息,然后将其从列队中移除,block默认值为True    

    1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果为空,此时程序将被阻塞(停在读取状态),直到从消息列队读到消息为止,如果设置了timeout,则会等待timeout秒,若还没读取到任何消息,则抛出"Queue.Empty"异常;

    2)如果block值为False,消息列队如果为空,则会立刻抛出"Queue.Empty"异常;

  7.Queue.get_nowait():相当Queue.get(False)

  8.Queue.put(item,[block[, timeout]]):将item消息写入队列,block默认值为True

    1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果已经没有空间可写入,此时程序将被阻塞(停在写入状态),直到从消息列队腾出空间为止,如果设置了timeout,则会等待timeout秒,若还没空间,则抛出"Queue.Full"异常;

    2)如果block值为False,消息列队如果没有空间可写入,则会立刻抛出"Queue.Full"异常;

  9.Queue.put_nowait(item):相当Queue.put(item, False)

六、进程池中的queue

  1.在进程池中使用queqe需要先引入manager模块(from multiprocessing import Manager),然后用Manager创建queue队列  q = Manager().Queue()

posted @ 2018-01-23 22:29  Leur  阅读(232)  评论(0编辑  收藏  举报