进程与进程池

一、开启进程的两种方式

进程的定义:正在进行的一个过程或者说一个任务,是个抽象化的概念。

 在开启子进程开辟新空间时,子进程需要拷贝父进程中的数据。
在 win 系统下,子进程会将父进程这个文件当成模块重新导入,需将发起开启子进程的操作放至main方法下;
在linux系统下,则不需要将开启子进程放至 main 方法下,但是为了系统的兼容性,一般都是统一放至 main 方法下。

方式一:

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=('we',))  # target 是表示需要执行的函数
    # agrs() 括号里边传的参数(元组形式)是传入至 task 里边
    p.start()  # 仅仅是向操作系统发起了一个开启子进程的指令,并不是表示子进程已经开启完毕
    print('main Process')

方式二:

 1 from multiprocessing import Process
 2 import time
 3 class MyProcess(Process):  # 自定义的一个进程(必须继承Process)
 4     def run(self):         # 这个是Process父类里边的一个绑定方法
 5         print("%s is running..."%self.name)
 6         time.sleep(3)
 7         print("%s is done"%self.name)
 8 
 9 
10 if __name__ == '__main__':
11     p=MyProcess()  # 实例化时需要用自己定义的类
12     p.start()      # 向操作系统发起一个开启子进程的信号,但是并不表示子进程开启完 
13                       # 毕(实际上是调用该子进程的p.run())
14     print('main Process')

二、进程(父进程和子进程)内存空间彼此隔离的验证

1.进程间数据不共享

 1 from multiprocessing import Process
 2 import time
 3 x=100
 4 def task():
 5     global x   # 声明 x 为全局变量
 6     x=0
 7     print('I am done')
 8 if __name__ == '__main__':
 9     p=Process()
10     p.start()
11     time.sleep(3)   # 若是没有这一步,则<可能>子进程还未执行完成直接调至执行父        
12                         # 进程的代码, 就是说,这一步是为了保证子进程能够顺利执行完成
13     print(x)

2.实现进程之间数据共享的方式

 1 from multiprocessing import Process,Manager
 2 import os
 3 def Foo(dic,list):
 4     dic[os.getpid()]=os.getpid()
 5     list.append(os.getpid())
 6     print(list)
 7 
 8 if __name__ == '__main__':
 9     with Manager() as manager:
10         dic=manager.dict() # 造一个空字典,可以在多个进程键共享和传递
11         list=manager.list() # 造一个空列表,可在多个进程间共享和传递
12                             # 实际上是每次都将列表复制一份,然后往里边加值
13         p_list=[]
14         for i in range(10):
15             p=Process(target=Foo,args=(dic,list))
16             p.start()
17             p_list.append(p)
18         for p in p_list:
19             p.join()
20         print(dic)

结果如下图

三、进程对象方法或者属性

1.join  (代表子进程的代码执行完毕)

 1 from multiprocessing import Process
 2 import time
 3 def task(name):
 4     print('%s is walking...'%name)
 5     time.sleep(3)
 6     print("%s is done..."%name)
 7 
 8 if __name__ == '__main__':
 9     p=Process(target=task,args=('BlackMan',))
10     p.start()
11     p.join()   # 代表子进程的代码已经执行完了
12     print('main Process')

2.多个子进程的运行

from multiprocessing import Process
import time
def task(x,y):
    print('%s is running...'%x)
    time.sleep(y)
    print('%s is done...'%x)


if __name__ == '__main__':
    p_list=[]
    start=time.time()
    for i in range(1,4):
        p=Process(target=task,args=('Processing-%s'%i,i))
        p_list.append(p)  # 这一步不要忘记写,否则直接执行父进程代码之后才开 
                                  # 始执行子进程代码
        p.start()    # p.start()写在这里的运行过程是多个子进程可以同时运行,可以 
                         #提高运行的效率
    for p in p_list:
        # p.start()    # p.start()如果写在这里运行过程就是先执行完一个子进程之 
                  # 后,再执行另一个子进程(就是串行的定义),这种执行方式效率比较低
        p.join()
    stop=time.time()
    print('creating Processing cost %s second'%(stop-start))
    print("it's turn to main Processing")

2.pid   (2.1 os.getpid()--获取当前进程的 id ;os.getppid()--获取父进程的id)

   2.1需要用到 os 模块

# getpid() 获取当前进程的id号
# getppid() 获取父进程的id号
from multiprocessing import Process
import time,os
def task(x):
    print("My id is %s..."%os.getpid())
    time.sleep(x)
    print('%s is gone...'%os.getpid())

if __name__ == '__main__':
    p=Process(target=task,args=(3,))
    p.start()
    print(p.pid)   # 从父进程角度查看子进程的 id 号
    p.join()
    print('main Processing,%s'%os.getppid())

 四、进程池

 1 from multiprocessing import Pool
 2 import time,os
 3 
 4 def Foo(i):
 5     time.sleep(2)
 6     print('in the pool',os.getpid())
 7     return i+100
 8 
 9 def Bar(arg):
10     print('exec done'.center(16,'-'),arg,os.getpid())
11 
12 if __name__ == '__main__':
13     pool=Pool(processes=2)   # 允许进程池同时有4个进程
14     print('---main---',os.getpid())
15     for i in range(10):
16         pool.apply_async(func=Foo,args=(i,),callback=Bar)
17         # callback指向了回调函数(可用于记录日志)
18         # pool.apply(func=Foo,args=(i,))  # 串行
19         pool.apply_async(func=Foo,args=(i,))  # 并行
20     print('end')
21     pool.close()
22 
23     # 进程池中进程执行完毕后再关闭,若注释掉,那么程序则直接关闭
24     pool.join()
原文地址:https://www.cnblogs.com/Smart1san/p/9295478.html