自从用了Python的多进程、多线程之后,发现了一些坑,感觉这个东西用起来还是没那么的方便呀~这里记录下我的一些简单的使用教程。
在Python中,存在多进程、多线程和协程,这里就介绍多进程和多线程的使用。
这里使用的库是multiprocessing
的多进程库Pool
,以及multiprocessing.dummy
的多线程库Pool
。这两个库的方法调用都是一致的,下面将介绍下。
方法 | 说明 |
---|---|
map(self, func, iterable, chunksize=None) |
同步进程池。Pool 类中的map 方法,与内置map 函数用法基本一致,融合了map 函数和apply_async() 函数的功能;它会使进程阻塞直到返回结果。 |
apply(self, func, args=(), kwds={}) |
同步进程池。该函数用于传递不定参数,按照加入进程池的顺序执行事件,每次执行完一个再执行另一个,主进程会被阻塞直到函数执行结束,无法获取返回值。 |
map_async(self, func, iterable, chunksize=None, callback=None, error_callback=None) |
异步进程池。map 的异步版本。 |
apply_async(self, func, args=(), kwds={}, callback=None, error_callback=None) |
异步进程池。异步执行,同时启动进程池中多个进程执行事件,可以获取事件返回值。 |
CPU 密集型操作
(CPU 操作指令比较多,如位数多的浮点运算)。IO 密集型操作
(读写数据操作较多的,比如爬虫)。需要注意的是,这里的进程是不能共享内存的,不然需要使用pickle实现数据的序列化
缺点:不能共享内存,每一个进程都有管理一份资源,非常消耗内存。
解决方案:可以通过使用静态对象的方式来共享内存,但是只允许读,不然数据的准确性无法保证。
def multi_process():
result = []
pool = ProcessPool(cpu_count())
for index in range(0, cpu_count(), 1):
result.append(pool.apply_async(func=get_data, args=(1, 2, 3,)))
pool.close()
pool.join()
# 获取回调
for res in result:
data1, data2, data3 = res.get()
print(data1, data2, data3)
def multi_thread():
pool = ThreadPool(max_thead_count_io)
pool.map(lambda item: get_data(item[0], item[1], item[2]), [[1, 2, 3], [2, 3, 4]])
pool.close()
pool.join()
from multiprocessing import cpu_count
from multiprocessing import Pool as ProcessPool
from multiprocessing.dummy import Pool as ThreadPool
# 最大的线程池线程数量
max_thead_count_cpu = cpu_count() * 6 - 1
max_thead_count_io = cpu_count() * 2 - 1
def get_data(one, two, third):
print(one, two, third)
return one, two, third
def multi_process():
"""
需要注意的是,这里的进程是不能共享内存的,不然需要使用pickle实现数据的序列化
缺点:不能共享内存,每一个进程都有管理一份资源,非常消耗内存。
:return:
"""
result = []
pool = ProcessPool(cpu_count())
for index in range(0, cpu_count(), 1):
result.append(pool.apply_async(func=get_data, args=(1, 2, 3,)))
pool.close()
pool.join()
# 获取回调
for res in result:
data1, data2, data3 = res.get()
print(data1, data2, data3)
def multi_thread():
pool = ThreadPool(max_thead_count_io)
pool.map(lambda item: get_data(item[0], item[1], item[2]), [[1, 2, 3], [2, 3, 4]])
pool.close()
pool.join()
if __name__ == '__main__':
multi_process()
multi_thread()