• 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()

  • 相关阅读:
    golang json处理
    关于单例模式中懒汉模式和饿汉模式的学习
    关于Lambda表达式的研究
    左值和右值得研究
    关于epoll的详解说明关于epoll的详解说明
    关于c++中条件变量的分析
    关于c++种std::function和bind的用法
    关于iterator_traits的使用
    STL容器之deque数据结构解析
    STL容器之Array的用法
  • 原文地址:https://www.cnblogs.com/peilanluo/p/8338192.html
Copyright © 2020-2023  润新知