-
-
- 进程
- 进程阻塞
- 定义一个进程把阻塞当做实参args
- 多进程
- threading和multiprocessing的一些理解
- 注意fork函数只在UnixLinuxMac上运行windows不可以
- 10_获取进程编号id
- 11_区分线程和进程获取名字id
- 小结__常用过去进程pid值得方法是去进程执行的目标函数内osgetpid 或osgetppid
- 20_subprocess标准子进程
- 21_subprocess标准子进程管道Pipe
- 小结____subprocess
- 30_多进程
- 40_进程通讯管道Pipe
- 50_进程池Pool
- 60_每个进程独享各自的list资源
- 61_共享数据各自进程独立进程multiprocessingQueuelist
- 62_共享数据各自进程独立进程multiprocessingArray
- 63_共享数据各自进程独立进程multiprocessingValueArray
- 进程
-
进程
进程阻塞:
multiprocessing.lock()
定义一个进程(把阻塞当做实参args):
#args=(,)必须是一个元组,num是for循环创建的第几个进程
multiprocessing.Process(target=showdatax,args=(lock,num)).start
多进程:
threading和multiprocessing的一些理解
- multiprocessing包是Python中的多进程管理包。
- 与threading.Thread类似,它可以利用multiprocessing.Process对象来创建一个进程。
- 该进程可以运行在Python程序内部编写的函数。
- 该Process对象与Thread对象的用法相同,也有start(), run(), join()的方法。
- 此外multiprocessing包中也有Lock/Event/Semaphore/Condition类 (这些对象可以像多线程那样,通过参数传递给各个进程),用以同步进程,其用法与threading包中的同名类一致。
- 所以,multiprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境。
注意,fork函数,只在Unix/Linux/Mac上运行,windows不可以
import os
pid = os.fork() #fork之后会记录父进程的值,子进程为0
if pid == 0:
print('哈哈1')
else:
print('哈哈2')
##运行结果
哈哈2
哈哈1
10_获取进程编号id:
获取当前进程的pid的方法为:getpid()
获取父进程的pid的方法为:getppid()
#coding=utf-8
import os
import time
# 注意,fork函数,只在Unix/Linux/Mac上运行,windows不可以
pid = os.fork()
if pid == 0:
print('哈哈1---pid = %d---ppid = %d----'%(os.getpid(), os.getppid()))
else:
print('哈哈2---pid = %d---'%os.getpid())
time.sleep(1)
11_区分线程和进程————获取名字、id
线程可以获取当前名字:threading.current_thread().name
进程可以获取当前名字:
p1 = multiprocessing.Process(target=showname,args=("go1",))
print(p1.name) #Process-1
也可以获取pid:
print(p1.pid) #7708
小结__常用过去进程pid值得方法是去进程执行的目标函数内os.getpid 或os.getppid
def showname(name):
time.sleep(2)
print("hello",name,os.getpid(),os.getppid())
20_subprocess标准子进程
import subprocess
pingP=subprocess.Popen(args="ping www.qq.com",shell=True)#shell进程
pingP.wait()#主进程等待子进程结束
print(pingP.pid)#进程ID
print(pingP.returncode)#返回值 成功结果返回0(至少表现出来是这样的)
##运行结果
正在 Ping www.qq.com [182.254.18.159] 具有 32 字节的数据:
来自 182.254.18.159 的回复: 字节=32 时间=20ms TTL=52
来自 182.254.18.159 的回复: 字节=32 时间=10ms TTL=52
来自 182.254.18.159 的回复: 字节=32 时间=11ms TTL=52
来自 182.254.18.159 的回复: 字节=32 时间=16ms TTL=52
182.254.18.159 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 10ms,最长 = 20ms,平均 = 14ms
11924
0
21_subprocess标准子进程+管道Pipe
import subprocess
import time
pingP=subprocess.Popen(args=["ping","www.qq.com"],
shell=True,
stdout=subprocess.PIPE)#shell进程
print(pingP.poll()) #进程状态
pingP.wait() #强制要求主进程等待子进程结束
time.sleep(0.0000001)
# pingP.kill() #杀死进程
print(pingP.stdout.read().decode("GBK"))#read是UTF-8,转化为GBK
print(pingP.pid) #进程ID
print(pingP.returncode) #返回值
##运行结果
None #子进程处于运行状态,未执行完,所以子进程返回None
正在 Ping www.qq.com [182.254.18.159] 具有 32 字节的数据:
来自 182.254.18.159 的回复: 字节=32 时间=9ms TTL=52
来自 182.254.18.159 的回复: 字节=32 时间=20ms TTL=52
来自 182.254.18.159 的回复: 字节=32 时间=7ms TTL=52
来自 182.254.18.159 的回复: 字节=32 时间=6ms TTL=52
182.254.18.159 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 6ms,最长 = 20ms,平均 = 10ms
4912
0 #强制要求主进程等待子进程完成才结束程序,子进程执行完,所以返回0
小结____subprocess
我们可以使用subprocess包来创建子进程,但这个包有两个很大的局限性:
1) 我们总是让subprocess运行外部的程序,而不是运行一个Python脚本内部编写的函数。
2) 进程间只通过管道进行文本交流。
以上限制了我们将subprocess包应用到更广泛的多进程任务。这样的比较实际是不公平的,因为subprocessing本身就是设计成为一个shell,而不是一个多进程管理包。
30_多进程
#-*- coding=utf-8 -*-
from multiprocessing import Process
import os
# 子进程要执行的代码
def run_proc(name):
print('子进程运行中,name= %s ,pid=%d...' % (name, os.getpid()))
if __name__=='__main__':
print('父进程 %d.' % os.getpid())
p = Process(target=run_proc, args=('test',))
print('子进程将要执行')
p.start()
p.join()
print('子进程已结束')
##运行结果
父进程 7488.
子进程将要执行
子进程运行中,name= test ,pid=10844...
子进程已结束
40_进程通讯——管道Pipe
import multiprocessing
def func(conn): #conn管道数据类型
conn.send([1,2,3,4,5])#发送数据
print(conn.recv())
conn.close()#关闭
if __name__=="__main__":
#如果duple=False,管道为单向,conn_A只能接受,conn_B只能发送
conn_A,conn_B=multiprocessing.Pipe(duplex=True) #开启管道 duplex默认为True,双向管道
print(type(conn_A),type(conn_B))
print(id(conn_A),id(conn_B))
#开启管道
p=multiprocessing.Process(target=func,args=(conn_B,))
p.start()
conn_A.send(["a","b","c"])
print(conn_A.recv())#收数据
p.join()
50_进程池Pool
import multiprocessing
import time
def go(i):
time.sleep(3)
print("第%d次"%i)
return i+100
def show(arg):
print("what---->",arg)
if __name__=="__main__":
pool=multiprocessing.Pool(5)#创建一个进程池有5个进程
print("start")
for i in range(10):
pool.apply_async(func=go,args=(i,),callback=show) #进程并发(5个一起执行),并发返回值,不阻塞主进程(主进程直接print("end")),callback获取返回的值,当做show的实参
#print(pool.apply(func=go, args=(i,))) #进程同步,阻塞主进程(等待所有子进程执行完,才print("end")),无法get值,处理结果
# print(pool.apply_async(func=go, args=(i,)).get()) #进程同步(一个一个执行),可以get出值,作另外的插座
#go,函数,args参数,callback处理结果
print("end")
pool.close()#封闭进程池,不再添加
pool.join()#等待
#apply_async异步,处理结果,start end->执行
#apply,不可以处理结果,start,end 之间执行
#print(pool.apply_async(func=go, args=(i,)).get()) 获取进程返回结果start,end 之间执行
##执行结果 #不阻塞主进程,直接print(”end“)
start
end
第0次
what----> 100
第1次
what----> 101
第2次
what----> 102
第3次
what----> 103
第4次
what----> 104
第5次
what----> 105
第6次
what----> 106
第7次
what----> 107
第8次
what----> 108
第9次
what----> 109
60_每个进程独享各自的list资源
import multiprocessing
import time
import os
#进程安全,可以收集,每个进程拷贝一份,不安全(list,set,tuple,dict)
datalist=[]#每个进程都有单独全局变量,每个进程拷贝一份,互相独立
def adddata(i):
datalist.append(i)
print("hello",i)
print(os.getpid(),datalist)#打印每个进程list
if __name__=="__main__":
for i in range(10):
p=multiprocessing.Process(target=adddata,args=(i,))
p.start()
time.sleep(10)
print("datalist",datalist)
for i in datalist:
print(i)
#有0到9,10个进程,每一个数字代表一个进程
hello 0
612 [0]
hello 2
5484 [2]
hello 1
9468 [1]
hello 3
11412 [3]
hello 4
11852 [4]
hello 6
6376 [6]
hello 7
4276 [7]
hello 5
12516 [5]
hello 8
6960 [8]
hello 9
11620 [9]
datalist []
61_共享数据(各自进程独立)——进程multiprocessing.Queue+list
import multiprocessing
import time
import os
#进程安全,可以收集,每个进程拷贝一份,不安全(list,set,tuple,dict)
datalist=[]#每个进程都有单独全局变量,每个进程拷贝一份,互相独立
queue=multiprocessing.Queue()
def adddata(queue,i):
datalist.append(i)
queue.put(datalist)#每个进程压入数据
# queue.put(["023"])#每个进程压入数据
print("hello",i)
print(os.getpid(),datalist)#打印每个进程list
if __name__=="__main__":
lastlist = [] #汇总结果
for i in range(10):
p=multiprocessing.Process(target=adddata,args=(queue,i,))#创建进程
# p.join()
p.start()#开启 #没有join,进程并发执行,乱序
#p.join() #进程是同步执行,乱序
listlite=queue.get()#get一次,取出一次数据
print("get",listlite,os.getpid())
lastlist+=listlite #结果汇总
print(lastlist)#打印结果
hello 0
13228 [0]
get [0] 8940
hello 1
11544 [1]
get [1] 8940
hello 2
12620 [2]
get [2] 8940
hello 3
2400 [3]
get [3] 8940
hello 4
get [4] 8940
10320 [4]
hello 5
11448 [5]
get [5] 8940
hello 6
12872 [6]
get [6] 8940
hello 7
8232 [7]
get [7] 8940
hello 8
8364 [8]
get [8] 8940
hello 9
2712 [9]
get [9] 8940
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
62_共享数据(各自进程独立)——进程multiprocessing.Array
import multiprocessing
temp=multiprocessing.Array("i",[1,2,3,4])#进程不安全数组不作为参数,安全,当作参数
def add(i):
temp[i]=100+i
print(id(temp))
for item in temp:
print(i,"---->",item)
if __name__=="__main__":
for i in range(2):
p=multiprocessing.Process(target=add,args=(i,))
p.start() #进程并发,乱序强资源,0和1进程,都有可能先打印
#运行结果
46016720
0 ----> 100
0 ----> 2
0 ----> 3
0 ----> 4
46147792
1 ----> 1
1 ----> 101
1 ----> 3
1 ----> 4
63_共享数据(各自进程独立)——进程multiprocessing.Value/Array
import multiprocessing
#Array Value共享数据,必须当作参数,
def f(n,a):
n.value=9999
a[0]=8888
if __name__=="__main__":
arr=multiprocessing.Array("i",[1,2,3,4,5]) #数据共享,当作参数
num=multiprocessing.Value("d",0.0) #d是一个类型,%d,%s,
p=multiprocessing.Process(target=f,args=(num,arr))
p.start()
p.join()
print(arr[:])
print(num.value)
[8888, 2, 3, 4, 5]
9999.0