Python实现多进程的方式主要有两种, 一种是使用 os库中的fork方法, 另一种 方法是使用multiprocessing库。这两种方法的区别在千前者仅适用于Unix/Linux操作系统,对Windows 不支持, 后者则是跨平台的实现方式。 由于本人使用的是windows电脑,因此演示结果只有multiprocessing的,但是也给出了fork的代码。本文是基于《Python爬虫与项目实践》一书。
fork方法
import os
def forktest():
print('current Process (%s) start ...' % (os.getpid()))
pid = os.fork() # windows don't support
if pid < 0:
print('error in fork')
elif pid == 0:
print('I am process (%s) and my parent process is (%s)', (os.getpid(), os.getppid()))
else:
print('I (%s) created a child process (%s).', (os.getpid(), pid))
其中,OS模块中的 getpid方法用于获取当前进程的ID , getppid方法 用于获取父进程的ID。
multiprocessing方法
multiprocessing库提供了一个Process类来表示一个进程对象,创建进程时只需要传入执行函数和函数对应得参数即可,然后使用start方法启动线程,使用join方法可以实现进程间得同步。
import os
from multiprocessing import Process
def run_proc(name):
print('Child process %s (%s) Running...' % (name, os.getpid()))
def multiprocessingtest():
print('Parent process %s.' % os.getpid())
for i in range(5):
p = Process(target= run_proc, args=(str(i),))
print('Process will start.')
p.start()
print('Process end.')
以上介绍了创建进程的两种方法,但是要启动大量的子进程,使用进程池批量创建子进程的方式更加常见,因为当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态生成多个进程,如果是上百个、上千个目标,手动去限制进程数量却又太过繁琐,这时候进程池Pool发挥作用的时候就到了。
multiprocessing模块提供了一个Pool类来代表进程池对象。Pool可以提供指定数量的进程供用户调用,默认大小是CPU的核数。 当有新的请求提 交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数巳经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来处理它。
import os, time, random
from multiprocessing import Pool, Process
def run_task(name):
print('Task %s (pid = %s) is running ...' %(name, os.getpid()))
time.sleep(random.random()*3)
print('Task %s end.' % name)
def pooltest():
print('current Process (%s) start ...' % (os.getpid()))
p = Pool(processes=3)
for i in range(5):
p.apply_async(run_task, args=(i,))
print('Waiting for all subprocesses done...')
p.close()
p.join()
print('All subprocesses done.')