爬虫知识一:使用multiprocessing模块创建多进程

1.子进程执行

创建子进程时,只需传入一个执行函数和函数的参数,即可完成一个Process实例的创建,start()启动进程,join()方法实现进程间的同步

import os
from multiprocessing import Process
def run_proc(name):
    #getpid是获得当前进程的进程号
    print 'Clild process %s (%s) Running...'%(name,os.getpid())

if __name__ == '__main__':
    print 'Parent process %s.'% os.getpid()
    for i in range(5):
        p = Process(target=run_proc,args=(str(i),))
        print 'Process will start.'
        #start()启动进程
        p.start()
        #join()方法实现进程间的同步
        p.join()
    print 'Process end.'
2.使用Pool类来代表进程池对象

import os,time,random
from multiprocessing import Process,Pool
def run_task(name):
    print 'Task %s (pid=%s) is running...'%(name,os.getpid())
    time.sleep(random.random()*3)
    print 'Task %s end.'% name
if __name__ == '__main__':
    print 'Current process %s.' % 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()
    #join()方法会等待所有子进程执行完毕,调用之前必须先调用close()方法
    #调用close()之后就不能继续添加新的Process了
    p.join()
    print 'All subprocesses done.'
3.进程间的通信

假如有创建了多个进程,则进程间的通信是必不可少的,Queue和Pipe的区别在于Pipe常用于两个进程间的通信,Queue经常用于多个进程间的通信

Queue:

from multiprocessing import Process,Queue
import os,time,random
#写数据进程:
#Put方法用以插入数据到队列中,两个可选参数blocked、timeout,如果blocked为True(默认值)
#并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间,如果超时,会抛出Queue.Full异常
#如果blocked为False,但该Queue已满,会立即抛出Queue.Full异常
def proc_write(q,urls):
    print 'Process(%s) is writing...' % os.getpid()
    for url in urls:
        q.put(url)
        print 'Put %s to queue...' % url
        time.sleep(random.random())
#读数据进程
#Get方法可以从队列读取并且删除一个元素。两个可选参数blocked、timeout
#如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常
#如果blocked为False,分两种情况:如果Queue有一个值可用,则立即返回该值;否则如果队列为空,则立即抛出Queue.Empty异常
def proc_read(q):
    print 'Process(%s) is reading...' % os.getpid()
    while True:
        url = q.get(True)
        print 'Get %s from queue,' % url

if __name__ == '__main__':
    #父进程创建Queue,并传递给各个子进程:
    q = Queue()
    proc_writer1 = Process(target=proc_write,args=(q,['url_1','url_2','url_3']))
    proc_writer2 = Process(target=proc_write,args=(q,['url_4','url_5','url_6']))
    proc_reader = Process(target=proc_read,args=(q,))
    #启动子进程proc_write,写入:
    proc_writer1.start()
    proc_writer2.start()
    #启动子进程proc_reader,读取:
    proc_reader.start()
    #等待proc_writer 结束:
    proc_writer1.join()
    proc_writer2.join()
    #proc_reader 进程是死循环,无法等待其结束,只能强行终止:
    proc_reader.terminate()
Pipe:
Pipe方法返回(conn1,conn2)代表一个管道的两个端,Pipe方法有duplex参数,如果duplex参数为TRUE(默认值),那么这个管道是双全工模式,也就是说conn1和conn2均可收发。若duplex为False,conn1只负责接收消息,conn2只负责发送消息,send和recv方法分别是发送和接收消息的方法

from multiprocessing import Process,Pipe
import random,time,os

def proc_send(pipe,urls):
    for url in urls:
        print 'Process(%s) send: %s' % (os.getpid(),url)
        pipe.send(url)
        time.sleep(random.random())

def proc_recv(pipe):
    while True:
        print 'Process(%s) recv: %s' % (os.getpid(),pipe.recv())
        time.sleep(random.random())

if __name__ == '__main__':
    pipe = Pipe()
    p1 = Process(target=proc_send,args=(pipe[0],['url_'+str(i) for i in range(10)]))
    p2 = Process(target=proc_recv,args=(pipe[1],))
    p1.start()
    p2.start()
    p1.join()
    p2.join()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值