Python之路PythonThread,第二篇,进程2

python3   进程2

僵尸进程处理方法:

3,创建二级子进程处理

4,在父进程中使用信号处理的方法忽略子进程发来的信号;

signal(SIGCHLD,DIG,IGN)

 1 # 创建二级子进场解决僵尸进程
 2 import os 
 3 
 4 #创建一级子进程
 5 pid = os.fork()
 6 
 7 if pid < 0:
 8     print('create process failed')
 9 elif pid == 0:
10     #创建二级子进程
11     p = os.fork()
12     if p < 0:
13         print('process failed')
14     elif p == 0:
15         print("做二级子进程任务")
16     else:
17         #一级子进程退出,使二级子进程成为孤儿
18         os._exit(0)
19 else:
20     #等待一级子进程退出
21     os.wait()
22     print("做父进程该做的")
View Code

 

更高效的进程创建方法

multiprocessing 模块(标准库模块)

创建的进程的步骤:

1,将要完成的事件封装成一个个函数;

2,使用multiprocessing提供的接口函数创建进程;

3,使新的进程和指定的函数相关联去完成函数中的工作;

4,对进程进行回收处理;

 1 import multiprocessing as mp 
 2 import os
 3 import time 
 4 
 5 #将要做的事封装为函数
 6 def th1():
 7     print(os.getppid(),"----",os.getpid())
 8     print('吃饭早饭')
 9     time.sleep(1)
10     print('吃饭午饭')
11     time.sleep(2)
12     print('吃饭晚饭')
13     time.sleep(3)
14 
15 def th2():
16     print(os.getppid(),"----",os.getpid())
17     print("睡午觉")
18     time.sleep(1)
19     print("睡觉")
20     time.sleep(3)
21 
22 def th3():
23     print(os.getppid(),"----",os.getpid())
24     print("打豆豆")
25     time.sleep(2)
26     print("打豆豆")
27     time.sleep(2)
28 
29 #创建3个子进程,生成子进程对象
30 #将函数和进程进行关联
31 p1 = mp.Process(target = th1)
32 p2 = mp.Process(target = th2)
33 p3 = mp.Process(target = th3)
34 
35 #启动进程让其执行对应的函数事件
36 #该函数即为这个就进程内容
37 p1.start()
38 p2.start()
39 p3.start()
40 
41 print("Parent PID:",os.getpid())
42 
43 # 阻塞等对应子进程的退出,然后回收子进程
44 p1.join()
45 p2.join()
46 p3.join()
47 
48 print("***********************")
49 # th1()
50 # th2()
51 # th3()
View Code

 注:1,函数当付给Process的target比那里后函数内容就是对应进程的进程内容,此时函数才有特殊性;

         2,多个子进程和父进程之间的执行相互不影响;

创建子进程:

Process() 类

参数: target指定要绑定的函数;

             name 给创建的进程起一个名字;

             args 需要一个元组,给target指定的函数按位置传参;

             kwargs 需要一个字典,给target指定的函数按键值传参;

#进程函数的使用
from multiprocessing import Process 
from time import sleep

def worker(sec):
    for i in range(3):
        sleep(sec)
        print("the worker xiaoming")

p = Process(name = 'worker',\
    target = worker,args = (2,),\
    kwargs = {})

p.start()

p.join()
View Code

 

 1 #进程函数的使用
 2 from multiprocessing import Process 
 3 from time import sleep
 4 
 5 def worker(sec,msg):
 6     for i in range(3):
 7         sleep(sec)
 8         print("the worker msg",msg)
 9 
10 p = Process(name = 'worker',\
11     target = worker,args = (2,),\
12     kwargs = {'msg':'You are a big man'})
13 
14 p.start()
15 
16 p.join()
View Code

 

 1 #进程函数的使用
 2 from multiprocessing import Process 
 3 from time import sleep
 4 
 5 a = 1
 6 
 7 def worker(sec,msg):
 8     #当worker作为子进程运行时,对全局量a 的修改只会
 9     #影响在子进程中a的值 ,对父进程没有影响
10     global a 
11     a = 1000
12     for i in range(3):
13         sleep(sec)
14         print("the worker msg",msg)
15     print(a)
16 
17 p = Process(name = 'worker',\
18     target = worker,args = (2,),\
19     kwargs = {'msg':'You are a big man'})
20 
21 p.start()
22 
23 p.join()
24 
25 #####
26 a=1000
View Code

 

 1 #进程函数的使用
 2 from multiprocessing import Process 
 3 from time import sleep
 4 
 5 a = 1
 6 
 7 def worker(sec,msg):
 8     #当worker作为子进程运行时,对全局量a 的修改只会
 9     #影响在子进程中a的值 ,对父进程没有影响
10     global a 
11     a = 1000
12     for i in range(3):
13         sleep(sec)
14         print("the worker msg",msg)
15     print(a)
16 
17 p = Process(name = 'worker',\
18     target = worker,args = (2,),\
19     kwargs = {'msg':'You are a big man'})
20 
21 p.start()
22 
23 #进程名称
24 print("进程名称:",p.name)
25 print("进程PID:",p.pid)
26 print('进程状态:',p.is_alive())
27 
28 p.join()
29 print('parent:',a)
View Code

 

Process() 类 ---->进程对象

属性方法:

print("进程名称", p.name)

print('进程PID',p.pid)

print('进程状态',p.is_alive())

 

启动子进程

start()

注:start() 时才真正的创建子进程,而不是Process时创建;

回收子进程

join(timeout)

timeout : 设置最长阻塞时间,如果超过这个时间还没有子进程退出,则不再继续等待;

注:内核会帮助应用层记录子进程的退出情况,当使用join函数时,内核会及时返回进程状态给应用层进行处理;

 1 import multiprocessing as mp 
 2 import os
 3 import time 
 4 
 5 def th1():
 6     print(os.getppid(),"----",os.getpid())
 7     print('吃饭早饭')
 8     time.sleep(1)
 9     print('吃饭午饭')
10     time.sleep(6)
11     print('吃饭晚饭')
12     time.sleep(3)
13 
14 def th2():
15     print(os.getppid(),"----",os.getpid())
16     print("睡午觉")
17     time.sleep(3)
18     print("睡觉")
19     time.sleep(3)
20 
21 def th3():
22     print(os.getppid(),"----",os.getpid())
23     print("打豆豆")
24     time.sleep(5)
25     print("打豆豆")
26     time.sleep(2)
27 
28 things = [th1,th2,th3]
29 process = []
30 
31 for th in things:
32     p = mp.Process(target = th)
33     process.append(p)
34 
35 for p in process:
36     p.start()
37 
38 for i in process:
39     i.join(1)
40 
41 print("++++++++++++++++++")
View Code

 

 

p.daemon

默认值为False,表示主进程运行结束后,不会影响子进程的运行,直到子进程运行完,进程才会结束;

如果设置为True, 则主进程运行完毕,则所有子进程也不再运行一起推出;

注:1,该属性的设置必须要在start前

        2,该属性的设置并不是讲进程设置为linux、unix中的守护进程;

守护进程: 生命周期长,与前端控制台无关,后台运行,一般用做系统进程或自动化运行进程;

 多进程编程:

优点:1,可以并行的执行多个任务,提高运行效率;

           2,空间独立,数据方便;

            3,创建方便;

缺点:进程的创建和销毁过程需要消耗较多的计算资源;

在需要频繁的创建和删除较多进程的情况下,资源消耗过多,不适宜使用多进程完成任务;

进程池技术:

1,创建进程池,在池内放入合适数量的进程;

2,将时间加入进程池的等待队列;

3,使用进程池内的进程不断的执行等待事件;

4,所有事件处理结束后关闭回收进程池;

 1 #!/usr/bin/python3
 2 
 3 import multiprocessing as mp
 4 from time import sleep
 5 import os
 6 
 7 def worker(msg):
 8     sleep(2)
 9     print(msg)
10 
11 #创建进程池对象,进程池中包含4个进程
12 pool = mp.Pool(processes = 4)
13 
14 for i in range(10):
15     msg = 'hello %d'%i
16     #像进程池加入要执行的事件
17     pool.apply_async(worker,(msg,))
18 #关闭进程池事件加入通道,即不能再向进程池中加入事件
19 pool.close()
20 #阻塞等待进程池出来事件结束后回收进程池
21 pool.join()
22 $ python3 pool1.py
23 hello 1
24 hello 0
25 hello 3
26 hello 2
27 hello 4
28 hello 5
29 hello 7
30 hello 6
31 hello 8
32 hello 9
View Code

 

Pool :

功能:创建进程池;

参数: processes 进程池中进程的数量;

apply_async()    

功能: 将异步的方式要执行的事件放入进程池;

参数: func  要执行的函数

             args   给函数按位置传参

            kwds   给函数按照键值传参

返回值: 返回事件执行后的返回值对象,可以通过调用get()函数获取事件函数return的内容;get() 函数获取事件函数return内容;

          

apply()

功能:按照顺序添加要执行的事件,执行一个添加一个;

close()  

功能:关闭进程池,使其不能再加入新的事件;

join()  

功能:阻塞等待进程池将事件都执行结束后回收进程池;

 1 #!/usr/bin/python3
 2 
 3 import multiprocessing as mp
 4 from time import sleep
 5 import os
 6 
 7 def worker(msg):
 8     sleep(2)
 9     print(msg)
10     return 'worker msg' + msg
11 
12 #创建进程池对象,进程池中包含4个进程
13 pool = mp.Pool(processes = 4)
14 
15 result = []
16 for i in range(10):
17     msg = 'hello %d'%i
18     #像进程池加入要执行的事件
19     r = pool.apply_async(worker,(msg,))
20     #pool.apply(worker,(msg,))
21     result.append(r)
22 
23 print(result)
24 #获取每个事件函数的返回值
25 for res in result:
26     print(res.get())
27 #关闭进程池事件加入通道,即不能再向进程池中加入事件
28 pool.close()
29 #阻塞等待进程池出来事件结束后回收进程池
30 pool.join()
View Code

 

map()

功能: 类似于内建函数map,将第二个参数的迭代对象中的数据逐个带入第一个函数作为参数。只不过兼顾了apply_async功能,将函数放入进程池

pool.map(fun, test)  ====>

for   i in test:

      pool.apply_async(fun, (i, ))

 1 $ cat pool4.py 
 2 #!/usr/bin/python3
 3 
 4 from multiprocessing import Pool
 5 import time
 6 
 7 def fun(fn):
 8     time.sleep(1)
 9     return fn * fn
10 
11 test = [1,2,3,4,5,6]
12 
13 print('顺序执行:')
14 s = time.time()
15 #map(fun,test)
16 for i in test:
17     fun(i)
18 e = time.time()
19 print('执行时间:',e - s)
20 
21 print('进程池执行')
22 pool = Pool(processes = 4)
23 r = pool.map(fun, test)
24 
25 pool.close()
26 
27 pool.join()
28 print('执行时间:',time.time() - e)
29 #####
30 $ python3 pool4.py 
31 顺序执行:
32 执行时间: 6.011707782745361
33 进程池执行
34 执行时间: 2.294673204421997
View Code

 

创建自己的进程类;

1,  继承Process类以获取原有的属性

2,实现自己需要的功能部分;

3,使用自己的类创建进程即可;

 1 from multiprocessing import Process
 2 import time
 3 
 4 class ClockProcess(Process):
 5     def __init__(self, *args, **kwargs):
 6         Process.__init__(self)
 7         self.value = value
 8 
 9     #在proces类中实现,现在重写这个函数
10     def run(self):
11         n = 5
12         while n > 0:
13             print('The time is {}'.\
14                   format(time.ctime()))
15             time.sleep(self.value)
16             n -= 1
17 
18 #s使用自己的进程类创建进程对象
19 p = ClockProcess(2)
20 #start后会自动执行run函数
21 p.start()
22 p.join()
View Code

 

 

进程间的通信:

不同的进程间进行数据的传输;

方法1: 文件进行进程间通信(和磁盘交互慢,不安全)

新的进程间通信方式:

管道  消息队列    共享内存  信号   套接字;

练习1:

 1 import os 
 2 
 3 #获取文件的大小
 4 size = os.path.getsize('file')
 5 
 6 #在创建进程前获取文件对象,子进程接受后父子
 7 #进程使用同一个文件偏移量会造成混乱
 8 # f = open('file','r')
 9 
10 pid = os.fork() 
11 
12 if pid < 0:
13     print("不想动")
14 #子进程拷贝前半部分
15 elif pid == 0:
16     n = size // 2 
17     fw = open('child','w')
18     with open('file','r') as f:
19         while True:
20             if n < 64:
21                 data = f.read(n)
22                 fw.write(data)
23                 break
24             data = f.read(64)
25             fw.write(data)
26             n -= 64
27     fw.close()
28 
29 #父进程后半部分
30 else:
31     fw = open('parent','w')
32     with open('file') as f:
33         f.seek(size // 2,0)
34         while True:
35             data = f.read(64)
36             if not data:
37                 break 
38             fw.write(data)
39     fw.close()
View Code

 

 

posted on 2018-06-12 20:50  微子天明  阅读(194)  评论(0编辑  收藏  举报

导航