20170530——进程_多进程_共享数据

来源:互联网 发布:海岛奇兵机枪升级数据 编辑:程序博客网 时间:2024/06/10 12:45

      • 进程
        • 进程阻塞
        • 定义一个进程把阻塞当做实参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 ospid = os.fork()     #fork之后会记录父进程的值,子进程为0if pid == 0:    print('哈哈1')else:    print('哈哈2')
##运行结果哈哈2哈哈1

10_获取进程编号id:

获取当前进程的pid的方法为:getpid()

获取父进程的pid的方法为:getppid()

#coding=utf-8import osimport 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  subprocesspingP=subprocess.Popen(args="ping www.qq.com",shell=True)#shell进程pingP.wait()#主进程等待子进程结束print(pingP.pid)#进程IDprint(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=52182.254.18.159Ping 统计信息:    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),往返行程的估计时间(以毫秒为单位):    最短 = 10ms,最长 = 20ms,平均 = 14ms119240
21_subprocess标准子进程+管道Pipe
import  subprocessimport  timepingP=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,转化为GBKprint(pingP.pid)    #进程IDprint(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=52182.254.18.159 的 Ping 统计信息:    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),往返行程的估计时间(以毫秒为单位):    最短 = 6ms,最长 = 20ms,平均 = 10ms49120       #强制要求主进程等待子进程完成才结束程序,子进程执行完,所以返回0
小结____subprocess

我们可以使用subprocess包来创建子进程,但这个包有两个很大的局限性:
1) 我们总是让subprocess运行外部的程序,而不是运行一个Python脚本内部编写的函数。
2) 进程间只通过管道进行文本交流。
以上限制了我们将subprocess包应用到更广泛的多进程任务。

这样的比较实际是不公平的,因为subprocessing本身就是设计成为一个shell,而不是一个多进程管理包。


30_多进程
#-*- coding=utf-8 -*-from multiprocessing import Processimport 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 multiprocessingdef  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  multiprocessingimport timedef  go(i):    time.sleep(3)    print("第%d次"%i)    return  i+100def  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“)startend0次what----> 1001次what----> 1012次what----> 1023次what----> 1034次what----> 1045次what----> 1056次what----> 1067次what----> 1078次what----> 1089次what----> 109
60_每个进程独享各自的list资源
import  multiprocessingimport timeimport os#进程安全,可以收集,每个进程拷贝一份,不安全(list,set,tuple,dict)datalist=[]#每个进程都有单独全局变量,每个进程拷贝一份,互相独立def adddata(i):    datalist.append(i)    print("hello",i)    print(os.getpid(),datalist)#打印每个进程listif __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 0612 [0]hello 25484 [2]hello 19468 [1]hello 311412 [3]hello 411852 [4]hello 66376 [6]hello 74276 [7]hello 512516 [5]hello 86960 [8]hello 911620 [9]datalist []
61_共享数据(各自进程独立)——进程multiprocessing.Queue+list
import  multiprocessingimport timeimport 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)#打印每个进程listif __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 013228 [0]get [0] 8940hello 111544 [1]get [1] 8940hello 212620 [2]get [2] 8940hello 32400 [3]get [3] 8940hello 4get [4] 894010320 [4]hello 511448 [5]get [5] 8940hello 612872 [6]get [6] 8940hello 78232 [7]get [7] 8940hello 88364 [8]get [8] 8940hello 92712 [9]get [9] 8940[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
62_共享数据(各自进程独立)——进程multiprocessing.Array
import multiprocessingtemp=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进程,都有可能先打印
#运行结果460167200 ----> 1000 ----> 20 ----> 30 ----> 4461477921 ----> 11 ----> 1011 ----> 31 ----> 4
63_共享数据(各自进程独立)——进程multiprocessing.Value/Array
import  multiprocessing#Array Value共享数据,必须当作参数,def  f(n,a):    n.value=9999    a[0]=8888if __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
原创粉丝点击