python笔记-多进程

2018-06-30 89次浏览 发表评论

os模块中fork函数

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

下面例子getpid()获取当前进程ID,getppid()是获取父进程ID:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os

print('进程({})启动...'.format(os.getpid()))

pid = os.fork()
str = 'aaaaaaaaa'
if pid == 0:
    print('我是子进程({}),父进程是:{},打印出:{}'.format(os.getpid(), os.getppid(), str))
else:
    print('我是父进程({}),子进程是:{},打印出:{}'.format(os.getpid(), pid, str))

执行结果:

进程(21736)启动...
我是父进程(21736),子进程是:21737,打印出:aaaaaaaaa
我是子进程(21737),父进程是:21736,打印出:aaaaaaaaa

multiprocessing模块

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

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from multiprocessing import Process
import os

str = 'aaaaaaaaaaaaaaaaaa'
def rp(name):
    print('{}的进程ID:{},打印:{}'.format(name, os.getpid(), str))

if __name__=='__main__':
    print('父进程({})启动...'.format(os.getpid()))
    p = Process(target=rp, args=('test',))    # 创建一个Process实例
    print('子进程启动...')
    p.start()             # 用start()方法启动
    p.join()              # join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步
    print('子进程结束...')

Pool

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

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from multiprocessing import Pool
import os
import time

def long_time_task(name):
    print('Run task %s (%s)...' % (name, os.getpid()))
    start = time.time()
    time.sleep(1)
    end = time.time()
    print('Task %s runs %0.2f seconds.' % (name, (end - start)))

if __name__ == '__main__':
    print('Parent process %s.' % os.getpid())
    p = Pool(3)   # pool如果不设置参数,默认是计算机CPU核心数
    for i in range(10):
        p.apply_async(long_time_task, args=(i,))
    print('Waiting for all subprocesses done...')
    p.close()     # 在join前必须调用close
    p.join()      # 等待所有子进程执行完毕
    print('All subprocesses done.')

执行结果:

Parent process 307.
Waiting for all subprocesses done...
Run task 0 (309)...
Run task 1 (310)...
Run task 2 (308)...          # 因为pool定义了3进程,一开始执行三个

Task 2 runs 1.00 seconds.    # 执行的程序延迟一秒,所以进程结束一个,继续补充一个进程:task3
Run task 3 (308)...
Task 0 runs 1.00 seconds.    # 又结束一个,下面补充一个 task4 ...
Run task 4 (309)...
Task 1 runs 1.00 seconds.
Run task 5 (310)...

Task 4 runs 1.00 seconds.
Run task 6 (309)...
Task 3 runs 1.00 seconds.
Run task 7 (308)...
Task 5 runs 1.00 seconds.
Run task 8 (310)...

Task 6 runs 1.00 seconds.
Run task 9 (309)...
Task 7 runs 1.00 seconds.
Task 8 runs 1.00 seconds.
Task 9 runs 1.00 seconds.
All subprocesses done.

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

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

使用subprocess.call可以调用外部进程。

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

评论

随便说点,聊聊天~