• 进程、多进程、进程间数据交互、进程同步、进程池


    多进程

    • 启用多进程,可以解决python调用计算机CPU多核运算的问题

    启动一个进程

    import multiprocessing
    import time
    
    def run(name):
        time.sleep(2)
        print('hello',name)
    
    for i in range(10):
        p = multiprocessing.Process(target=run,args=('man %s'%i,))
        p.start()
    

    from multiprocessing import Process
    import os
    
    def info(title):
        print(title)
        print('module name:', __name__)
        print('parent process:', os.getppid())#父进程ID
        print('process id:', os.getpid())#当前进程ID
        print("
    
    ")
    
    def f(name):
        info('33[31;1mfunction f33[0m')#子进程的info,子进程的PPID=主进程的PID
        print('hello', name)
    
    if __name__ == '__main__':
        info('33[32;1mmain process line33[0m')#主进程的info
    #在window,主进程的PPID=pycharm的PID
        p = Process(target=f, args=('bob',))
        p.start()
        p.join()
    
    • 每一个进程都是由一个父进程启动的

    进程间数据交互

    • 不管哪种方式,都是找一个中间代理,相当于不同国家的人交流需要找一个翻译
    • 不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用以下方法:

    进程间数据交互(通信)的方式

    1.Queues

    • 使用方法跟threading里的queue差不多。这里的queue不是线程中的,线程中的queue只能在创建线程的主进程之间由它的线程使用
    from multiprocessing import Process, Queue
    #用法和线程的queue是一样的,但这里引入的是进程的queue
    def f(q):
        q.put([42, None, 'hello'])
    
    if __name__ == '__main__':
        q = Queue()
        p = Process(target=f, args=(q,))
        p.start()
        print(q.get())    # prints "[42, None, 'hello']"
        p.join()
    

    2.Pipes管道

    • 管道实例化后会产生两个通道,分别交给两个进程
    • 通过send和recv来交互数据,这是一个双向的管道,child和parent可以互相收发
    from multiprocessing import Process, Pipe
    
    def f(conn):
        conn.send([42, None, 'hello'])
        conn.close()
    
    if __name__ == '__main__':
        parent_conn, child_conn = Pipe()
        p = Process(target=f, args=(child_conn,))
        p.start()
        print(parent_conn.recv())  # prints "[42, None, 'hello']"
        p.join()
    

    3.Managers经理/代理

    • 以代理的方式在进程间共享字典或列表形式的数据
    from multiprocessing import Process, Manager
    import os
    def f(d, l):
        d[1] = '1'
        d['2'] = 2
        d[0.25] = None
        l.append(os.getpid())
        print(l)
    
    if __name__ == '__main__':
        with Manager() as manager:
            d = manager.dict()#生成一个字典,在多个进程间共享和传递
    
            l = manager.list(range(5))#生成一个列表含5个初始值,在多个进程间传递和共享
            p_list = []
            for i in range(10):
                p = Process(target=f, args=(d, l))
                p.start()
                p_list.append(p)
            for res in p_list:
                res.join()
    
            print(d)
            print(l)
    

    进程同步LOCK

    • 进程不能操作同一块数据,那么进程锁的意义是什么?
    • 进程锁存在的意义是保证各进程在屏幕输出时不会乱
      比如:进程1,打印hello word 1,进程2打印hello word 2,没有锁,进程1的打印还没结束,进程2进来了,就可能造成混乱。(window上不会发生,linux上测试,2.7以下python)
    from multiprocessing import Process, Lock
    
    def f(l, i):
        l.acquire()
        try:
            print('hello world', i)
        finally:
            l.release()
    
    if __name__ == '__main__':
        lock = Lock()
    
        for num in range(10):
            Process(target=f, args=(lock, num)).start()
    

    进程池

    • 进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。
    • 进程池中有两个方法:
    • apply同步执行-串行
    • apply_async异步执行-并行
    from  multiprocessing import Process, Pool
    import time,os
    
    def Foo(i):
        time.sleep(2)
        print('in process',os.getpid())
        return i + 100
    
    def Bar(arg):
        print('-->exec done:', arg)
    
    if __name__ == '__main__':
        pool = Pool(5)#同时允许5个进程进入进程池,其他进程挂起
    
        for i in range(10):
            pool.apply_async(func=Foo, args=(i,), callback=Bar)#callback回调函数
            # pool.apply(func=Foo, args=(i,))
    
        print('end')
        pool.close()#这里join一定是在close之后,且必须要加join,否则主进程不等待创建的子进程执行完毕
        pool.join()  # 进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
    

    from concurrent.futures import ThreadPoolExecutor线程池必用模块

    from concurrent.futures import ProcessPoolExecutor进程池必用模块

    参考文档

  • 相关阅读:
    swagger Unable to render this definition
    企业应用向ASP.NET Core迁移
    .NET Core EF框架使用SQL server 2008数据库分页问题:Incorrect syntax near 'OFFSET'. Invalid usage of the option NEXT in the FETCH statement
    .NET Core应用中使用分布式缓存及内存缓存
    .NET Core Session的使用方法
    .NET Core 2.1中的HttpClientFactory最佳实践
    转载:ZooKeeper Programmer's Guide(中文翻译)
    Python【map、reduce、filter】内置函数使用说明(转载)
    Python使用基础
    Redis Sentinel:集群Failover解决方案(转载)
  • 原文地址:https://www.cnblogs.com/limich/p/7477105.html
Copyright © 2020-2023  润新知