zoukankan      html  css  js  c++  java
  • 多线程,进程随笔

    多进程之子进程与父进程关系

    from multiprocessing import Pool, Process
    import time
    import os
    def info(title):
        print(title)
        print('module name:', __name__)
        print('parent process:', os.getppid())
        print('process id', os.getpid())
    
    
    def f(name):
        time.sleep(5)
        info('function f')
        print('hello', name)
    
    
    if __name__ == '__main__':
        info('main line')
        p = Process(target=f, args=('Bob',))
        p.daemon = True  # 设置为守护进程
        p.start()
        p.join()
    
    # 当进程不使用join时,如果p主进程为守护进程,那么f子进程可能还没执行完,p父进程就退出了
    # f可能会变成僵尸进程(孤儿), 所以如果希望父进程等待子进程执行完任务再退出,则需要使用join
    # 当p主进程不是守护进程时,则p不需要join也会等待子进程执行完才退出
    
    # 为了通常不管需不需要设为守护进程,我们都希望子进程能完成任务,那么每次新建进程时都使用join吧
    

    多进程之自定义创建进程方式

    import multiprocessing as mp
    def foo(q):
        q.put('hello')
    
    if __name__ == '__main__':
        ctx = mp.get_context('spawn')  # 通过获取上下文方式设置创建进程方式
        q = ctx.Queue()
        p = ctx.Process(target=foo, args=(q,))
        p.start()
        print(q.get())
        p.join()
    
    # 多进程支持多种创建方式spawn,fork, forkserver
    # spawn 支持unix和windows,这个方式在windows是默认的创建方式,这个方法效率低于fork和forkserver
    # fork 仅支持unix,unix平台默认创建方式为fork,
    # forkserver 支持能在unix平台传递文件描述符的管道平台
    
    # 不同的创建进程方式之间是不兼容的,特别是锁创建,使用fork上下文,是不能启动使用spawn或forkserver方式创建的进程
    

    多进程之Queue队列实现进程间数据共享

    from multiprocessing import Pool, Process, 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())  # 父进程获取子进程的数据
        p.join()
    # 进程间的数据是不共享的,如果需要交换数据,需要使用进程模块的Queue队列方法
    # 队列是线程和进程安全的
    

    多进程之Pipe管道实现进程间数据通信

    from multiprocessing import Pool, Process, Queue, 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())  # 使用另一个管道接受数据
        p.join()
    
    # 通过管道也能实现进程间数据通信
    

    多进程之Lock实现数据同步

    from multiprocessing import Pool, Process, Queue, Pipe, Lock
    def f(l, i):
        l.acquire()  # 加锁后,其他进程将被阻塞,只有最先调用acquire获得锁的进程才能执行
        try:
            print('hello world', i)
        finally:
            l.release()  # 调用release释放锁后,其他进程将又会抢占资源
    
    
    if __name__ == '__main__':
        lock = Lock()
        for num in range(10):
            Process(target=f, args=(lock, num)).start()  # 由于进程创建后就立即执行,所以该例子最终变成串行方式
    
    # 通过加锁使进程间对于同一个资源的使用保持同步,避免脏数据,加锁后,得到锁的进程会锁定资源,其他进程将进入阻塞状态,直到锁被释放,所有进程又将开始抢占资源,直到某一个进程又获得了锁,这时其他没有获得锁的进程又被阻塞
    

    多进程之进程间数据状态共享

    from multiprocessing import Pool, Process, Queue, Pipe, Lock, Value, Array
    def f(n, a):
        n.value = 3.1415927
        for i in range(len(a)):  # 子进程对父进程传进来的数据进行修改
            a[i] = -a[i]
    
    
    if __name__ == '__main__':
        num = Value('d', 0.0)  # 第一个参数为数据类型,d为double双精度浮点型,适合单个值状态共享
        arr = Array('i', range(10))  # 第一个参数是数据的类型,i为整型,适合多个值状态共享
    
        p = Process(target=f, args=(num, arr))
        p.start()
        p.join()
    
        print(num.value)
        print(arr[:])  # 父进程访问子访问子进程操作过的数据,这个数据通常讲,进程间的数据是独立的,但是通过这种方式,实现了进程间的数据也能实现状态共享,这里的数组使用[:]分片表示将数据拷贝了一份
    
    # 上面进程间同步时需要我们手动加锁,避免进程对同一个资源同时修改,我们也可以使用Value或Array两个方法,实现进程间的数据状态共享,其内部也是通过加锁方式避免了脏数据产生
    

    多进程之Manager代理,实现进程间数据共享

    from multiprocessing import Pool, Process, Queue, Pipe, Lock, Value, Array, Manager
    def f(d, l):
        d[1] = '1'
        d['2'] = 2
        d['0.25'] = None
        l.reverse()
    
    
    if __name__ == '__main__':
        with Manager() as manager:
            d = manager.dict()  # 由manager代理的python 字典对象
            l = manager.list(range(10))  # 由manager代理的python列表对象
    
            p = Process(target=f, args=(d, l))  # 由子进程进行操作代理的数据
            p.start()
            p.join()
    
            print(d)  # 父进程访问数据时与子进程数据保持同步
            print(l)
    
    # 通过Manager来代理进程间操作python对象,这样也能实现进程间数据共享。
    #Manager支持代理的对象list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value 
    
  • 相关阅读:
    pycharm配置svn
    python发送邮件
    HttpRunner接口自动化测试框架--7.执行测试
    HttpRunner接口自动化测试框架--6.skip跳过用例
    HttpRunner接口自动化测试框架--5.hook机制
    python读取csv文件
    HttpRunner接口自动化测试框架--常见问题
    HttpRunner接口自动化测试框架--4.参数化操作(parameters)
    易错点
    pycharm破解
  • 原文地址:https://www.cnblogs.com/zengchunyun/p/7127538.html
Copyright © 2011-2022 走看看