美文网首页
python进程

python进程

作者: 奔跑的老少年 | 来源:发表于2018-08-01 14:17 被阅读0次

    同一进程线程之间可相互共用数据,子线程可访问主线程的队列,如下示例子线程p可访问主线程的q:

    import threading
    import queue #线程queue
    from multiprocessing import Process,Queue #进程queue
    
    def f(qq):
        # q = queue.Queue()
        qq.put([42,None,'hello'])
    
    if __name__ == '__main__':
        q = queue.Queue() #线程queue
        p = threading.Thread(target=f,args=(q,))#开启一个子线程
        p.start()
        print(q.get())
    
    [42, None, 'hello']
    

    进程之间是相互独立的,不能相互访问。如要使进程之间通信,可使用队列Queue或Pipe管道化。

    一、进程队列
    进程不能访问线程队列。如下示例子进程p访问线程队列q时报错,错误信息为TypeError: can't pickle _thread.lock objects,因该线程队列没有序列化与反序列化后传给另一个进程

    import threading
    import queue #线程queue
    from multiprocessing import Process,Queue #进程queue
    
    def f(qq):
        # q = queue.Queue()
        qq.put([42,None,'hello'])
    
    
    if __name__ == '__main__':
        q = queue.Queue() #线程queue
        # p = threading.Thread(target=f,args=(q,))
        p = Process(target=f,args=(q,)) #启动一个子进程
        p.start()
        print(q.get())
    
    TypeError: can't pickle _thread.lock objects
    

    进程只能访问进程queue,如下子进程p可访问父进程队列q,实际上该子进程和父进程访问的不是同一个q,一个进程并不能直接访问另一个进程的内存。该父进程的q被pickle 序列化之后,再反序列化放到子进程内存,所以父进程和子进程内的是两个去,不是一个共享q。通过序列化将一个进程数据传递给另一个进程,但不是修改即子进程不能修改父进程的q,父进程也不能修改子进程的q。线程之间则不同,他们无需序列化就可共用一份数据,且可修改这同一分数据:

    import threading
    import queue #线程queue
    from multiprocessing import Process,Queue #进程queue
    
    def f(qq):
        # q = queue.Queue()
        qq.put([42,None,'hello'])
    
    
    if __name__ == '__main__':
        # q = queue.Queue() #线程queue
        # p = threading.Thread(target=f,args=(q,))
        q = Queue()
        p = Process(target=f,args=(q,)) #启动一个子进程
        p.start()
        print(q.get())
    
    [42, None, 'hello']
    

    二、Pipe管道化
    管道化就是连接了通信的两端:发送方和接收方,可相互通信如下示例:

    from multiprocessing import Pipe,Process
    
    def f(conn):
        conn.send(['hello,father'])
        print(conn.recv())
        conn.close()
    
    if __name__ == '__main__':
        parent_conn,child_conn = Pipe()
        print(parent_conn,child_conn)
        p = Process(target=f,args=(child_conn,))
        p.start()
        print(parent_conn.recv())
        parent_conn.send('hello,son')
        p.join()
    

    Pipe()会返回两个对象即发送方和接收方,管道化和Queue一样也只是实现了进程间数据的传递,并不是共享

    进程之间共享递数据可用Manager,我们无需担心两个进程会不会同时修改一个数据造成数据错误,即无需我们考虑加锁处理该问题,Manager内部自己处理。我们加锁是为防止在屏幕上打印的时候出现混乱:

    from multiprocessing import Manager,Process,Lock
    import os
    
    def f(dict1,list1):
    
        dict1[1] = '1'
        dict1['name'] = 'Tim'
        dict1[0.3] = None
        list1.append(os.getpid()) #拼接进程号
        print('f list-->',list1)
    
    
    if __name__ ==  '__main__':
        lock = Lock()
        manager = Manager()
        d = manager.dict() #创建进程间共享和传递的字典
        l = manager.list(range(5))#创建进程间共享和传递的列表
        p_list = []
        for i in range(5):
            p = Process(target=f,args=(d,l))
            p.start()
            p_list.append(p)
        for res in p_list: #等待所有进程执行完毕
            res.join()
        print('main dict:',d)
        print('main list',l)
    
    f list--> [0, 1, 2, 3, 4, 10404]
    f list--> [0, 1, 2, 3, 4, 10404, 8332]
    f list--> [0, 1, 2, 3, 4, 10404, 8332, 9892]
    f list--> [0, 1, 2, 3, 4, 10404, 8332, 9892, 10720]
    f list--> [0, 1, 2, 3, 4, 10404, 8332, 9892, 10720, 10688]
    main dict: {0.3: None, 1: '1', 'name': 'Tim'}
    main list [0, 1, 2, 3, 4, 10404, 8332, 9892, 10720, 10688]
    

    相关文章

      网友评论

          本文标题:python进程

          本文链接:https://www.haomeiwen.com/subject/qpchvftx.html