Python 多进程(1)

进程与线程的初步了解


计算机系统中的各类任务,例如打开word,播放器,均有各自的进程(Process)。进程是资源分配的最小单位。
而一个进程至少拥有一个线程,是一对多的关系。例如,播放电影的进程中,音频和视频是同步播放的,它们是两个子任务,即为隶属于统一进程的不同线程(Thread)。线程是程序执行的最小单位。
每个线程可以共享进程的内存,且单独拥有线程栈来存储数据。

并发与并行的区别

多线程和多进程最重要的一个特点就是并发和并行。简单来说,多个任务在单核cpu上进行,通过各种进程调度规则(例如先来先服务,时间片轮转法等)实现一种宏观的同时进行(实际上是交替进行的),即为并发。
而在多核cpu上,任务数量少于核数时,可以做到真正的同时进行,即为并行。
并发和并行在系统中都很常见,多线程任务采用并发还是并行由计算机分配。

python实现多进程


Linux下Python多进程展示

linux下独有的fork()函数,可以根据父进程复制一个子进程,其中父进程返回子进程的id,子进程返回0。

import  os
#输出父进程的id
print('%s process start'%os.getpid())
#fork()函数生成子进程
pid=os.fork()
#子进程的返回结果
if pid==0:
    #getpid()和getppid()分别返回当前进程id和父进程的id
    print('I am %s line and my parent is %s process'%(os.getpid(),os.getppid()))
#父进程的返回结果
else:
    print('I (%s) just created a child process (%s).' % (os.getpid(), pid))
18740 process start
I 18740 just created a child process 18741.
I am 18741 line and my parent is 18740 process

Windows下Python多进程展示

windows下没有fork()函数,可以使用multiprocessing模块。

import os
from multiprocessing import Process
def func(name):
    #输出当前进程的id
    print('%s child process %s start'%(name,os.getpid()))
if __name__=='__main__':
    #输出父进程的id
    print('Parent process %s start'%os.getpid())
    #以定义好的函数创建进程,并指定参数
    p=Process(target=func,args=('study',))
    #子进程开始
    p.start()
    #join()函数确保该子进程执行完毕后才继续进行
    p.join()
    print('All processes finished')
Parent process 9120 start
study child process 16612 start
All processes finished

使用multiprocessing中的Pool方法,建立一个进程池

p=Pool(n)

参数n为进程池中可容纳的最大进程数。
使用进程池的apply_async()方法,这是一种异步非阻塞的运行方法,即进程池的所有进程根据规则随时切换运行,比阻塞式的apply()方法要快。
调用join()之前必须先调用close(),只有关闭进程池,才能让里面的进程运行完毕。

import os,time,random
from multiprocessing import Pool
def run_fun(name):
    start=time.time()
    print('%s child process %s start'%(name,os.getpid()))
    time.sleep(random.random()*3)
    end=time.time()
    print('%s child process takes %0.2f seconds'%(name,end-start))
if __name__=='__main__':
    print('Parent process %s start'%os.getpid())
    #参数n为进程池中可容纳的最大进程数。
    p=Pool(4)
    for i in range(5):
        p.apply_async(run_fun,args=(i,))
    print('waiting for all process finished')
    #关闭进程池之后就不能继续添加新的Process了
    p.close()
    p.join()
    print('All process finished')
Parent process 12380 start
waiting for all process finished
0 child process 16952 start
1 child process 17588 start
2 child process 5768 start
3 child process 8756 start
2 child process takes 1.48 seconds
4 child process 5768 start
0 child process takes 1.84 seconds
1 child process takes 1.86 seconds
4 child process takes 0.52 seconds
3 child process takes 2.59 seconds
All process finished

Process finished with exit code 0

进程之间通信

队列(queue)

multiprocessing模块里的Queue方法可以生成队列,一个进程将数据放到队列里,另一个进程从队列里把数据拿出来,这样就实现了进程之间的通信。

from multiprocessing import Queue,Process
import os
def write(q):
    print('process %s are writing'%os.getpid())
    #把数据放进队列中
    for value in ['a','b','c']:
        q.put(value)
def read(q):
    print('process %s are reading'%os.getpid())
    #不停地从队列中取数据
    while True:
        value=q.get()
        print(value)
if __name__=='__main__':
    q=Queue()
    #定义两个进程实现通信
    p=Process(target=write,args=(q,))
    pp=Process(target=read,args=(q,))
    p.start()
    pp.start()
    p.join()
    #由于进程2中存在死循环,所以手动终止该进程
    pp.terminate()

输出:

process 13944 are writing
process 7764 are reading
a
b
c

管道(pipe)

multiprocessing模块里的Pipe方法可以生成管道。管道会返回两个对象,作为管道的两个端口。
默认这两个端口是双开的,即Pip(duplex=True),即均可进可出,设为False则为一进一出。

from multiprocessing import Pipe,Process
import os
def write(p):
    print('process %s are writing'%os.getpid())
    #向管道里发送数据
    p.send('Hello world')
def read(p):
    print('process %s are reading'%os.getpid())
    #不停地从管道里读取数据
    while True:
        print('I read:',p.recv())
if __name__=='__main__':
    p=Pipe()
    #分别给两个进程各分配一个端口
    p1=Process(target=write,args=(p[0],))
    p2=Process(target=read,args=(p[1],))
    p1.start()
    p2.start()
    p1.join()
    #进程1结束之后,往管道里发送数据,进程2依然会不停的读取
    p[0].send('fuck')
    #若2s内没有数据进入管道,则强制结束进程
    p2.join(2)
    print('All finished')

输出:

process 10084 are writing
process 2536 are reading
I read: Hello world
I read: fuck
All finished

猜你喜欢

转载自blog.csdn.net/qq_18831501/article/details/80216036
今日推荐