首页 > 技术文章 > python 进程的创建

leishenwudi 2020-09-12 17:32 原文

python多进程基本的三个步骤

1、引入模块multiprocessing

2、用进程类创建进程

3、start进程

进程可以加快程序运行速度,例如:

import multiprocessing
import time
def sing(num):
    for i in range(num):
        print('sing')
        time.sleep(0.5)
def dance(num):
    for i in range(num):
        print('dance')
        time.sleep(0.5)
if __name__ == '__main__':
    before = time.time()
    sing(3)
    dance(3)
    dis = time.time() - before
    print(dis)

 

 

 花费了大约三秒,下面用进程来实现

import multiprocessing
import time
def sing():
    for i in range(3):
        print('sing')
        time.sleep(0.5)
def dance():
    for i in range(3):
        print('dance')
        time.sleep(0.5)
if __name__ == '__main__':
    before = time.time()
    one = multiprocessing.Process(target=sing)
    two = multiprocessing.Process(target=dance)
    one.start()
    two.start()
    one.join()
    two.join()
    dis = time.time() - before
    print(dis)

 

 

 只用了1.6s

上面是没有带参数的进程创建,下面看看带参数的进程创建

进程的参数带入有两种格式,一是args元组形式,而实kwargs列表形式,args是按照从前往后的顺序进行传参的,kwargs是按照键值对相对应的关系进行传参的

import multiprocessing
import time
def sing(num):
    for i in range(num):
        print('sing')
        time.sleep(0.5)
def dance(num):
    for i in range(num):
        print('dance')
        time.sleep(0.5)
if __name__ == '__main__':
    before = time.time()
    one = multiprocessing.Process(target=sing,args=(3,))
    two = multiprocessing.Process(target=dance,args=(3, ))
    one.start()
    two.start()
    one.join()
    two.join()
    dis = time.time() - before
    print(dis)

 

 

 创建成功

下面是列表形式传多个参数

import multiprocessing
import time
def sing(num,name):
    for i in range(num):
        print(name)
        print('sing')
        time.sleep(0.5)
def dance(num,name):
    for i in range(num):
        print(name)
        print('dance')
        time.sleep(0.5)
if __name__ == '__main__':
    before = time.time()
    one = multiprocessing.Process(target=sing,args=(3,'lilei'))
    two = multiprocessing.Process(target=dance,args=(3, 'meimei'))
    one.start()
    two.start()
    one.join()
    two.join()
    dis = time.time() - before
    print(dis)

 

 正确

如果多个参数中有些事元组,有些是普通字符,有些是数字,怎么通过元组形式进行区分呢?

在这里建议使用字典形式

下面进行字典形式的传参

import multiprocessing
import time
def sing(num,name):
    for i in range(num):
        print(name)
        print('sing')
        time.sleep(0.5)
def dance(num,name):
    for i in range(num):
        print(name)
        print('dance')
        time.sleep(0.5)
if __name__ == '__main__':
    before = time.time()
    one = multiprocessing.Process(target=sing,kwargs={'name' : 'DC', 'num' : 3})
    two = multiprocessing.Process(target=dance,kwargs={'name' : 'KZL', 'num' : 3})
    one.start()
    two.start()
    one.join()
    two.join()
    dis = time.time() - before
    print(dis)

 

 用字典形式传参就不会导致传参不正确

 

到现在就知道了怎么创建进程了,下面看一些注意事项

★默认子进程不会等待子进程,父进程结束了子进程也不会结束

也从一个例子说起

import multiprocessing
import time
def sing():
    for i in range(3):
        print("DC")
        print('sing')
        time.sleep(0.5)
if __name__=='__main__':
    print("演出开始")
    one = multiprocessing.Process(target=sing)
    one.start()
    print('演出结束')

 

 主进程演出已经结束了,但是DC还在唱歌,这里就说明了子进程并没有因为父进程的结束而结束

这里可以通过join函数实现这里进程的同步,让子进程结束了父进程才结束

import multiprocessing
import time
def sing():
    for i in range(3):
        print("DC")
        print('sing')
        time.sleep(0.5)
if __name__=='__main__':
    print("演出开始")
    one = multiprocessing.Process(target=sing)
    one.start()
    one.join()
    print('演出结束')

 

 实现了,这里需要注意,join必须在start的后面,如果有多个进程,每个子进程的join函数都需要在所有子进程的start函数后面。

join相当于强制执行当前进程

同时可以通过设置守护进程,让主进程结束后,子进程跟着结束

import multiprocessing
import time
def sing():
    for i in range(3):
        print("DC")
        print('sing')
        time.sleep(0.5)
if __name__=='__main__':
    print("演出开始")
    start_process = multiprocessing.Process(target=sing)
    start_process.daemon = True
    start_process.start()
    time.sleep(1)
    print('演出结束')

 

 因为只有大约1S的时间,所以DC只唱了两次歌

 

接着就需要看看进程的进程号获取

获取进程号可以通过os模块,当让也可以用multiprocessing.current_process().pid

os.getpid:获取当前进程的进程号

os.getppid:获取父进程的进程号

定义进程处理类

此种方法会定义一个新的进程process类的新类

需要重新写__init__,然后将需要执行的目标函数放在run函数,一旦调用该类的start函数,就会自动调用该run函数

import multiprocessing
import time
# 定义进程处理类
class MyProcess(multiprocessing.Process):
    def __init__(self,name,delay,count):
        super().__init__(name=name)
        self.__delay = delay
        self.count = count
    def run(self):
        for i in range(self.count):
            print("目前进程号是:{0},进程的名称是:{1}".format(multiprocessing.current_process().pid,multiprocessing.current_process().name))
if __name__=='__main__':
    one = MyProcess(name='leilei', count=3, delay=0.1)
    one.start()

 

 需要注意,设置进程名字那里需要用super调用父类的方法。

run函数也可以直接调用,但是此时就没有子进程生成,而是主进程直接调用该函数

进程控制

Process类进程控制的方法

  • terminate(self)         关闭进程
  • is_alive(self)           判断进程是否存活
  • join(self,out)           进程强制执行

在关闭进程之前必须判断进程是否存活

守护进程

守护进程是运行在后台的特殊进程,当其专属进程结束时,守护进程也会结束。

守护进程就相当于监听。

创立守护进程时,只要将daemon设置为True。

import multiprocessing,time
def sing():
    two = multiprocessing.Process(target=protect, daemon=True)
    two.start()
    for i in range(5):
        a = 'I\'m sing'
        print('I\'m sing')
        time.sleep(0.5)
def protect():
    for i in range(10):
        print("I'm protecting you!")
        time.sleep(0.5)
if __name__ == '__main__':
    one = multiprocessing.Process(target=sing)
    one.start()

I'm sing
I'm protecting you!
I'm sing
I'm protecting you!
I'm sing
I'm protecting you!
I'm sing
I'm protecting you!
I'm sing
I'm protecting you!

I'm protecting you!应该打印10次,但是因为sing函数结束了,所以守护进程protect也结束了

 

推荐阅读