python笔记—进程笔记

多进程模式:在操作系统上一个任务就是一个进程,例如打开一个笔记本,打开一个浏览器,打开一个word文档或者打开播放器,单核cpu上的任务都是轮流进行的,只是cpu处理太快我们没感觉,多核CPU可以实现多个   任务同时进行,进程的调度都是于系统进行,进程本身不能控制。

多线程模式:线程是进程中的一项子任务,列如在word文档中会有拼写检查,打印,打字需要同时运行,在一个进程运行的多个子任务就叫线程

多进程多线程模式:启动多个进程和多线程可以同时执行的任务更多,模型也更复杂

多进程

Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。

1 import os
2 
3 print('Process (%s) start...' % os.getpid())
4 # Only works on Unix/Linux/Mac:
5 pid = os.fork()
6 if pid == 0:
7     print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))
8 else:
9     print('I (%s) just created a child process (%s).' % (os.getpid(), pid))

运行结果如下:

Process (876) start...
I (876) just created a child process (877).
I am child process (877) and my parent is 876.

由于Windows没有fork调用,上面的代码在Windows上无法运行。

multiprocessing

由于Windows没有fork调用,需要用另一个模块multiprocessing

multiprocessing模块中提供了Process类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束:

 # 子进程要执行的代码
def run_proc(name):
    # 获取子进程ID
    print('Run child process %s (%s)...' % (name,os.getpid()))

if __name__ == '__main__':
    # 获取父进程ID
    print('Parent process %s.'% os.getpid())
    # 创建一个Process 实例,调用函数和函数的参数。生成一个字进程
    p = Process(target=run_proc,args=('test',))
    print('Chid process will start')
    # 启动子进程
    p.start()
    # 等待子进程结束后再往下运行,通常用于进程间的同步
    p.join()
    print('Child process end.')

创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start()方法启动,这样创建进程比fork()还要简单。

join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。

Pool

如果要启动大量的子进程,可以用进程池的方式批量创建子进程:

def long_time_task(name):
    print('Run task %s (%s)...'% (name,os.getpid()))
    start = time.time()
    # 等待时间
    time.sleep(random.random() * 3)
    end = time.time()
    print('Task %s runs %0.2f seconds'% (name,(end - start)))

if __name__ == '__main__':
    # 获取父进程
    print('Parent process %s.' % os.getpid())
    # 同时执行四个子进程
    p = Pool(4)
    # 每个线程分工调用五次函数,由于默认是4个线程,多出的一个需要其中一个线程完成后再执行
    for i in range(5):
        p.apply_async(long_time_task,args=(i,))
    print('Waiting for all subprocesses done... ')
    # 停止调用进程
    p.close()
    p.join()
    print('All subprocesses done.')

进程间通信

Process之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python的multiprocessing模块包装了底层的机制,提供了QueuePipes等多种方式来交换数据。

我们以Queue为例,在父进程中创建两个子进程,一个往Queue里写数据,一个从Queue里读数据:

def write(q):
    print('Process to write:%s'% os.getpid())
    for value in ['A','B','C']:
        print('Put %s to queue...'% value)
        q.put(value)
        time.sleep(random.random())
def read(q):
    print('Process to read:%s'% os.getpid())
    while True:
        value = q.get(True)
        print('Get %s from queue.'% value)

if __name__ == '__main__':
    # 父进程创建Queue,并传给各个子进程
    q = Queue()
    pw = Process(target=write,args=(q,))
    pr = Process(target=read,args=(q,))
    # 启动子进程pw,写入:
    pw.start()
    # 启动子进程pr,读取:
    pr.start()
    # 等待pw进程结束
    pw.join()
    # pr进程是死循环,无法等待其结束,只能强行终止
    pr.terminate()

小结

在Unix/Linux下,可以使用fork()调用实现多进程。

要实现跨平台的多进程,可以使用multiprocessing模块。

进程间通信是通过QueuePipes等实现的。

摘自廖雪峰老师网站:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431927781401bb47ccf187b24c3b955157bb12c5882d000

 

posted @ 2019-04-02 09:27  袁麻麻  阅读(165)  评论(0)    收藏  举报