多进程
windows系统可以使用multiprocessing模块‘Process’类来创建子进程,批量启动进程的(‘pool’)、用于进程间通信的队列(‘Queue’)和管道(‘Pipe’)
我们通过Process
类创建了进程对象,通过target
参数我们传入一个函数来表示进程启动后要执行的代码,后面的args
是一个元组,它代表了传递给函数的参数。Process
对象的start
方法用来启动进程,而join
方法表示等待进程执行结束。
Lock锁
import multiprocessing
def A(lock,i):
with lock:
print(i)
if __name__ == "__main__":
lock = multiprocessing.RLock()
process_list = []
for i in range(10):
p = multiprocessing.Process(target=A,args=(lock,i))
p.start()
process_list.append(p)
for p in process_list:
p.join()
Pipe管道
def A(conn):
conn.send(['a','b','c']) #发送的数据
print('A',conn.recv()) #收到的数据
conn.close() #关闭
if __name__ == "__main__":
conn_a,conn_b = multiprocessing.Pipe()
p = multiprocessing.Process(target = A,args = (conn_a,))
p.start()
conn_b.send([1,2,3,4,5,6,7]) #发送数据给conn_a
print('main',conn_b.recv())
B发送A接收
import multiprocessing
def A(conn):
while 1:
print('A',conn.recv()) #收到的数据
#conn.close() #关闭
if __name__ == "__main__":
conn_a,conn_b = multiprocessing.Pipe()
p = multiprocessing.Process(target = A,args = (conn_a,))
p.start()
while 1:
input_ = input('>>')
conn_b.send(input_) #发送数据给conn_a
使用try 一定要用except
1.Queue.qsize()
返回队列的大致长度。
2.Queue.empty()
如果队列是空的,返回 True ,反之返回 False 。
3.Queue.full()
如果队列是满的,返回 True ,反之返回 False 。
4.Queue.put(obj[, block[, timeout]])
将 obj 放入队列。如果可选参数 block 是 True (默认值) 而且 timeout 是 None (默认值), 将会阻塞当前进程,直到有空的缓冲槽。
5.Queue.put_nowait(obj)
相当于 put(obj, False)。
6.Queue.get([block[, timeout]])
从队列中取出并返回对象。如果可选参数 block 是 True (默认值) 而且 timeout 是 None (默认值), 将会阻塞当前进程,直到队列中出现可用的对象。
7.run()
表示进程活动的方法。
8.start()
启动进程活动。
每个进程对象最多只能调用一次。它安排对象的 run() 方法在一个单独的进程中调用。
9.join([timeout])
如果可选参数 timeout 是 None (默认值),则该方法将阻塞,直到调用 join() 方法的进程终止。
一个进程可以合并多次。进程无法并入自身,因为这会导致死锁。尝试在启动进程之前合并进程是错误的。
10.name
进程的名称。该名称是一个字符串,仅用于识别目的。它没有语义。可以为多个进程指定相同的名称。初始名称由构造器设定。 如果没有为构造器提供显式名称,则会构造一个形式为 ‘Process-N1:N2:…:Nk’ 的名称,其中每个 Nk 是其父亲的第 N 个孩子。
11.is_alive()
返回进程是否还活着。粗略地说,从 start() 方法返回到子进程终止之前,进程对象仍处于活动状态。
当进程退出时,它会尝试终止其所有守护进程子进程。
12.task_done()
指出之前进入队列的任务已经完成。由队列的消费者进程使用。对于每次调用 get() 获取的任务,执行完成后调用 task_done() 告诉队列该任务已经处理完成。如果 join() 方法正在阻塞之中,该方法会在所有对象都被处理完的时候返回 (即对之前使用 put() 放进队列中的所有对象都已经返回了对应的 task_done() ) 。如果被调用的次数多于放入队列中的项目数量,将引发 ValueError 异常 。
管道可以又放又取 队列不能
share
# 全局变量不可以进程共享
import multiprocessing
import os
data = []
def List():
global data
data.append(1)
data.append(2)
data.append(3)
print('p',os.getpid(),data)
if __name__ == '__main__':
p = multiprocessing.Process(target=List,args=()).start() # 子进程
data.append('a') # 脚本主进程
data.append('b')
data.append('c')
print('main',os.getpid(),data)
全局变量不共享
1809 ['a', 'b', 'c']
1810 [1, 2, 3]
Queue
# 队列可以进程共享
import multiprocessing
import os
queue = multiprocessing.Queue()
# 注意队列只能单向,要么是父进程插入子进程取出,要么是子进程插入父进程取出
def func(myq):
print(os.getpid())
myq.put([1, 2, 3, 4]) # 子进程插入
if __name__ == '__main__':
print(os.getpid())
# queue.put(['a','b']) # 这里若是脚本父进程先插入了,子进程就没法再插入了
p = multiprocessing.Process(target=func, args=(queue,))
p.start()
print(queue.get()) # 脚本父进程取出
进程数据共享
import multiprocessing
def func(num):
num.value = 10
if __name__ == '__main__':
# multiprocessing.Value可以在不同进程之间共享数据
num = multiprocessing.Value('d', 1) # double float
print(num.value) # 单单num返回的结果 Synchronized wrapper for c_double(1.0)
p = multiprocessing.Process(target=func, args=(num,))
p.start()
p.join()
print(num.value)
进程列表数组共享
import multiprocessing
def func(num):
num[2] = 9999
if __name__ == '__main__':
# 不同进程之间实现数组共享
num = multiprocessing.Array('i', [1, 2, 3, 4, 5, 6]) # i代表int类型
print(num[:])
p = multiprocessing.Process(target=func, args=(num,))
p.start()
p.join()
print(num[:])
进程字典列表共享
import multiprocessing
def func(mydict, mylist):
mydict["小娜"] = "是机器人"
mydict["lalal"] = "是机器名"
mylist.append(11)
mylist.append(22)
mylist.append(33)
if __name__ == "__main__":
mydict = multiprocessing.Manager().dict()
mylist = multiprocessing.Manager().list(range(5))
p = multiprocessing.Process(target=func, args=(mydict, mylist))
p.start()
p.join()
print(mylist)
print(mydict)