python并发编程之多进程

一,multiprocessing模块结束

python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程。Python提供了multiprocessing。
    multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似。

  multiprocessing模块的功能众多:支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。

    需要再次强调的一点是:与线程不同,进程没有任何共享状态,进程修改的数据,改动仅限于该进程内。

二,Process类的介绍

p=Process(target=task,args=('子进程',))

#由该类实例化得到的对象,表示一个子进程中的任务(尚未启动)

强调:

1,args指定的为传给target函数的位置参数,是一个元祖形式,如果只有一个参数的话,一定记住加逗号。

2.target表示调用对象,即子进程要执行的任务。

3.args表示调用对象的位置参数元祖。

4 .   p.start()  只是在向操作系统发送一个开启子进程的信号。

三,创建并开启子进程的两种方式:

方式一:(用默认类的方式)

# from multiprocessing import Process
# import time
#
# def task(x):
# print('%s is running' %x)
# time.sleep(3)
# print('%s is done' %x)
#
# if __name__ == '__main__':
# # Process(target=task,kwargs={'x':'子进程'})
# p=Process(target=task,args=('子进程',)) # 如果args=(),括号内只有一个参数,一定记住加逗号
# p.start() # 只是在操作系统发送一个开启子进程的信号
#
# print('主')


方式二:(自定义类的方式)

# from multiprocessing import Process
# import time
#
# class Myprocess(Process): #自定义类
# def __init__(self,x):
# super().__init__()
# self.name=x
#
# def run(self): #把子进程想执行的任务放到run下面的函数体代码
# print('%s is running' %self.name) #self是p
# time.sleep(3)
# print('%s is done' %self.name)
#
# if __name__ == '__main__':
# p=Myprocess('子进程1')
# p.start() #等于是自动调用 p.run()
# print('主')

补充:
僵尸进程和孤儿进程

一:僵尸进程(有害)
  僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。


父进程代码运行完毕后,等待子进程代码运行完进入僵尸状态(保留PID,其他都没了,就叫僵尸状态),最后父进程统一发起回收
子进程僵尸的操作。

二:孤儿进程(无害)

  孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。


四,进程内存空间彼此隔离

from multiprocessing import Process
n=100 #在windows系统中应该把全局变量定义在if __name__ == '__main__'之上就可以了
def work():
    global n
    n=0
    print('子进程内: ',n)


if __name__ == '__main__':
    p=Process(target=work)
    p.start()
    print('主进程内: ',n)


用以上方法来证明,内存空间是彼此隔离的。

在子进程中用global声明了全局变量,且把n=100改为0,当主进程进行打印的时候,n=100没变,说明内存空间是隔离的。

五,进程对象的方法或属性详解。

join方法

join方法,是父进程在原地等,等到子进程运行完毕后,才执行下一行代码

#1、join
# from multiprocessing import Process
# import time
#
# def task(name):
# print('%s is running ' %name)
# time.sleep(3)
# print('%s is done ' % name)
#
#
# if __name__ == '__main__':
# p=Process(target=task,args=('子进程1',))
# p.start()
# p.join() # 让父进程在原地等待,等到子进程运行完毕后,才执行下一行代码
# print('主')


启动进程与join进程可以简写为:

# from multiprocessing import Process
# import time
#
# def task(name,n):
# print('%s is running ' %name)
# time.sleep(n)
# print('%s is done ' % name)
#
#
# if __name__ == '__main__':

#
# p_l=[]
# start=time.time()
# for i in range(1,4):
# p=Process(target=task,args=('子进程%s' %i,i))
# p_l.append(p)
# p.start()
#
# # print(p_l)
# for p in p_l:
# p.join()
#
# stop=time.time()
#
# print('主',(stop-start))



PID方法:
是进程的ID号

p1子进程是在父进程中造出来的。在父进程中查看子进程的ID,用p1.pid
如果在子进程中看自己的ID,用 os.getpid()


一,父进程内查看子PID的方式:

# pid
# from multiprocessing import Process
# import time
# import os
#
# def task(n):
# print('%s is running ' %os.getpid())
# time.sleep(n)
# print('%s is done ' % os.getpid())
#
#
# if __name__ == '__main__':
# p1=Process(target=task,args=(10,))
# # print(p1.pid)
# p1.start()
# print(p1.pid) # 父进程内查看子pid的方式
# print('主')



二,查看父进程自己的PID(用 os.getppid())
from multiprocessing import Process
import time
import os

def task():
print('自己的id:%s 父进程的id:%s ' %(os.getpid(),os.getppid()))
time.sleep(200)

if __name__ == '__main__':
p1=Process(target=task)
p1.start()
print('主',os.getpid(),os.getppid())
# 爹=》主--》儿子




原文地址:https://www.cnblogs.com/fxc-520520/p/9295350.html