一:多进程的优点、应用场景
耗CPU计算时多进程速度大于多线程,可以最大化利用CPU计算。多进程有更强的容错性,一个进程出错不会影响其他进程。通常不需要考虑锁和同步资源的问题。
二:进程使用方法
- 实例化
multiprocessing.Process
,调用Threading的方法去进行多线程编程 - 写子类继承
multiprocessing.Process
,重写相应的方法
说明:当程序简单时可使用实例化方法,当程序较复杂的时候,实现逻辑较多,第二种方法。 - linux 中
os.fork()
拷贝父进程全部数据资源,fork之后的代码父子进程都会继续运行。 -
concurrent.futures
下的ProcessPoolExecutor
就像上次的多线程那样操作,非常类似。
三: 进程间通信
- 共享全局变量不适用多进程,多线程可以用。因为多进程的数据资源是隔离开的,相互独立无法共享变量。
- 需要明确的是多进程间的通信和多线程不一样,不能用
queue.Queue
作为队列要用multiprocessing.Queue
-
multiprocessing
的Queue
不能用于 Pool ( 进程池),需要用multiprocessing
的Manager
的Queue
,需要实例化:queue = Manager().Queue()
-
multiprocessing
的Pipe
:用法recevid_pipe, send_pipe = Pipe()
只能适用于两个指定的进程。性能高于queue
四:进程的实例代码
#方法一:multiprocessing.Process
import multiprocessing
import requests
def download_html(i):
url = f'https://www.baidu.com/s?ie=UTF-8&wd={i}'
response = requests.get(url).text
print(response)
ids = list(range(100))
# 方法一
for i in range(5):
p = multiprocessing.Process(target=process, args=(i,))
p.start()
# 方法二
def multipro_main(ids ):
pool = multiprocessing.Pool(10)
pool.map(download_html, ids)
pool.close()
pool.join()
# 方法三
from multiprocessing.dummy import Pool as thpool
def thread_pool(ids ):
pool = thpool(10)
pool.map(download_html, ids)
pool.close()
pool.join()
# 方法四 (推荐,和多线程接口类似)
from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor(10) as executor:
executor.map(download_html, ids)
五:总结
concurrent.futures
是一个非常不错的库,多线程和多进程无缝切换,非常方便。这个库设计思路也很好,为后面的写异步协程的代码也打下基础。
代码位置:github.com/rieuse/learnPython