美文网首页
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