51好读  ›  专栏  ›  dwzb

python多进程基础

dwzb  · 掘金  ·  · 2018-03-13 06:10

正文

python多进程基础

本文首发于 知乎
python中的多进程编程方式和多线程非常相似,几乎可以说只是换了一些函数,有了之前讲过的多线程基础,很多地方我就只展示一些代码,在涉及到差别的地方再着重说明。

本文分为如下几个部分

  • 事先说明
  • 最简单的多进程
  • 类的形式
  • 进程池
  • 进程之间内存独立
  • 队列
  • pipe
  • value
  • 进程锁

事先说明

有两点在写代码时需要注意

  • 使用多进程时,最好在文件中编写代码,用cmd来执行,在jupyter经常无法得到想要的结果
  • 创建进程的代码一定要放在 if __name__ == '__main__' 里面

最简单的多进程

import multiprocessing
import time
def myfun(num):
time.sleep(1)
print(num + 1)
if __name__ == '__main__':
for i in range(5):
p = multiprocessing.Process(target = myfun, args = (i, ))
p.start()

另外, join is_alive daemon name current_process 等也都是一样的。

类的形式

import multiprocessing
import requests
from bs4 import BeautifulSoup
class MyProcess(multiprocessing.Process):
def __init__(self, i):
multiprocessing.Process.__init__(self)
self.i = i
def run(self):
url = 'https://movie.douban.com/top250?start={}&filter='.format(self.i*25 )
r = requests.get(url)
soup = BeautifulSoup(r.content, 'html.parser')
lis = soup.find('ol', class_='grid_view').find_all('li')
for li in lis:
title = li.find('span', class_="title").text
print(title)
if __name__ == '__main__':
for i in range(10):
p = MyProcess(i)
p.start()

进程池

import requests
from bs4 import BeautifulSoup
from multiprocessing import Pool, current_process
def get_title(i):
print('start', current_process().name)
title_list = []
url = 'https://movie.douban.com/top250?start={}&filter='.format(i*25)
r = requests.get(url)
soup = BeautifulSoup(r.content, 'html.parser')
lis = soup.find('ol', class_='grid_view').find_all('li')
for li in lis:
title = li.find('span', class_="title").text
# return title
title_list.append(title)
print(title)
return(title_list)
if __name__ == '__main__':
pool = Pool()
for i in range(10):
pool.apply_async(get_title, (i, ))
pool.close()
pool.join()
print('finish')

这里要说明一下

  • 使用 Pool 时,不指定进程数量,则默认为CPU核心数量
  • 核心数量对应电脑的(任务管理器-性能)逻辑处理器数量而不是内核数量(我的电脑2个内核,有4个逻辑处理器,所以这里默认使用4个进程)
  • 进程数量可以是成百上千,并不是说最大开启进程数量为4,只要用 Pool(10) 就可以同时开启10个进程进行抓取
  • 不过要注意一点,无论多线程还是多进程,数量开启太多都会造成切换费时,降低效率,所以慎重创建太多线程与进程

进程之间内存独立

多进程与多线程最大的不同在于,多进程的每一个进程都有一份变量的拷贝,进程之间的操作互不影响,我们先来看看下面的例子

import multiprocessing
import time
zero = 0
def change_zero():
global zero
for i in range(3):
zero = zero + 1
print(multiprocessing.current_process().name, zero)
if __name__ == '__main__':
p1 = multiprocessing.Process(target = change_zero)
p2 = multiprocessing.Process(target = change_zero)
p1.start()
p2.start()
p1.join()
p2.join()
print(zero)

运行结果如下

Process-1 1
Process-1 2
Process-1 3
Process-2 1
Process-2 2
Process-2 3
0

上面结果显示,新创建的两个进程各自把值增加到了3,二者不是一起将其加到了6的。同时,主进程的值还是0。所以说每个进程都是将数据拷贝过去自己做,并没有将结果与其他进程共享。

但是对于写入文件则不同

import






请到「今天看啥」查看全文