python多进程并发+pool多线程+共享变量

一.多进程

当计算机运行程序时,就会创建包含代码和状态的进程。这些进程会通过计算机的一个或多个CPU执行。不过,同一时刻每个CPU只会执行一个进程,然后不同进程间快速切换,给我们一种错觉,感觉好像多个程序在同时进行。例如:有一个大型工厂,该工厂负责生产电脑,工厂有很多的车间用来生产不同的电脑部件。每个车间又有很多工人互相合作共享资源来生产某个电脑部件。这里的工厂相当于一个爬虫工程,每个车间相当于一个进程每个工人就相当于线程线程是CPU调度的基本单元。

也就是进程间是独立的,这表现在内存空间,上下文环境;而线程运行在进程空间内.也就是同一进程产生的线程共享同一内存空间.

需要注意的是单核CPU系统中,真正的并发是不可能的.

1.顺序执行 

2.多进程并发 注意除了时间的加速意外也要看看函数返回值的写法,带有多进程的map,是返回一个列表

import requests
import re
import time
from multiprocessing import Pool
from multiprocessing.dummy import Pool as ThreadPool
def spyder(url):
    # res = []
    res = {'init:':'hello'}
    print('hahah:{}'.format(url))
    time.sleep(1)
    # res.append(url)
    res.update({'entr:'+url:url})
    return res

def use_process():
    urls = ["https://www.qiushibaike.com/text/page/{}/".format(str(i)) for i in range(0, 4)]

    start_1 = time.time()
    #获取函数返回结果
    res1 = []
    for url in urls:
        res_ = spyder(url)
        res1.append(res_)
    end_1 = time.time()
    print("单进程:", end_1 - start_1)
    print('res1:', res1)

    # 获取函数返回结果
    #  进程池
    start_2 = time.time()
    pool = Pool(processes=2)
    res2 = pool.map(spyder, urls)
    pool.close()
    pool.join()
    print('res2:', res2)
    end_2 = time.time()
    print("2进程:", end_2 - start_2)

    # 获取函数返回结果
    # 进程池
    start_3 = time.time()
    pool = Pool(processes=4)
    res3 = pool.map(spyder, urls)
    pool.close()
    pool.join()
    print('res2:', res3)
    end_3 = time.time()
    print("4进程:", end_3 - start_3)
if __name__ == "__main__":
    use_process()

二.多线程

实际上由于GIL(全局解释器锁)的限制,哪个线程想要执行代码就需要去申请锁,否则只能等着,所以这个锁阻碍了真正的多线程并发,这是解释器cpython的锅,一般不推荐用多线程,而是用多进程multiprocess来绕过GIL.

2.1 thread多线程

import time
import _thread
from threading import Thread
# 使用线程锁,防止线程死锁
mutex = _thread.allocate_lock()
def test(d_num):
    d_num.append(89)
    print("test: %s"% str(d_num))
def test1(d_num):
    print("test1: %s"% str(d_num))
def main():
    d_num = [100, 58]
    t1 = Thread(target=test, args=(d_num,))
    t2 = Thread(target=test1, args=(d_num,))
    t1.start()
    time.sleep(1)
    t2.start()
    time.sleep(1)

if __name__ == '__main__':
    main()

2.2 多线程队列版

import time
import _thread
from threading import Thread
import queue
# 使用线程锁,防止线程死锁
mutex = _thread.allocate_lock()
frame_queue = queue.Queue()
def test(d_num):
    print("test: %s" % str(d_num))
    for i in range(d_num):
        frame_queue.put(i)

def test1():
    while 1:
        if frame_queue.empty() != True:
            # 从队列中取出图片
            value = frame_queue.get()
            print('==value:', value)
            time.sleep(1)
        else:
            break
def main():
    d_num = 10
    t1 = Thread(target=test, args=(d_num,))
    t1.start()
    t2 = Thread(target=test1)
    t2.start()

if __name__ == '__main__':
    main()

2.3 注意传参与多进程的区别,线程池

from functools import partial
from itertools import repeat
from multiprocessing import Pool, freeze_support


def func(a, b):
    return a + b

def main():
    a_args = [1, 2, 3]
    second_arg = 1
    with Pool() as pool:
        L = pool.starmap(func, [(1, 1), (2, 1), (3, 1)])
        print('L:', L)
        M = pool.starmap(func, zip(a_args, repeat(second_arg)))
        print('M:', M)
        N = pool.map(partial(func, b=second_arg), a_args)
        print('N:', N)
main()

import requests
import re
import time
from multiprocessing import Pool
from multiprocessing.dummy import Pool as ThreadPool
def spyder(url):
    # res = []
    res = {'init:':'hello'}
    print('hahah:{}'.format(url))
    time.sleep(1)
    # res.append(url)
    res.update({'entr:'+url:url})
    return res

def use_process():
    urls = ["https://www.qiushibaike.com/text/page/{}/".format(str(i)) for i in range(0, 4)]

    start_1 = time.time()
    #获取函数返回结果
    res1 = []
    for url in urls:
        res_ = spyder(url)
        res1.append(res_)
    end_1 = time.time()
    print("单进程:", end_1 - start_1)
    print('res1:', res1)

    # 获取函数返回结果
    #  进程池
    start_2 = time.time()
    pool = Pool(processes=2)
    res2 = pool.map(spyder, urls)
    pool.close()
    pool.join()
    print('res2:', res2)
    end_2 = time.time()
    print("2进程:", end_2 - start_2)

    # 获取函数返回结果
    # 进程池
    start_3 = time.time()
    pool = Pool(processes=4)
    res3 = pool.map(spyder, urls)
    pool.close()
    pool.join()
    print('res2:', res3)
    end_3 = time.time()
    print("4进程:", end_3 - start_3)

def use_threadpool():
    urls = [["https://www.qiushibaike.com/text/page/{}/".format(str(i))] for i in range(0, 4)]
    print('urls:', urls)
    # 线程池
    start = time.time()
    pool = ThreadPool(processes=4)
    res = pool.starmap(spyder, urls)
    pool.close()
    pool.join()
    end = time.time()
    print('res:', res)
    print("4线程:", end - start)
if __name__ == "__main__":
    # use_process()
    use_threadpool()

实际应用将图片路径和名字传入,用zip方式打包传参

import os

import cv2
import time
import itertools
from multiprocessing.dummy import Pool as ThreadPool

SIZE = (75,75)
SAVE_DIRECTORY='thumbs'
def save_img(filename,save_path):
    save_path+= filename.split('/')[-1]
    im = cv2.imread(filename)
    im=cv2.resize(im,SIZE)
    cv2.imwrite(save_path,im)

if __name__ == '__main__':
    path='./data/testlabel'
    print(path)
    output_path='./data/thumbs/'
    if not os.path.exists(output_path):
        os.mkdir(output_path)
    print(output_path)
    imgs_list_path=[os.path.join(path,i) for i in os.listdir(path)]
    print(len(imgs_list_path))
    start_time=time.time()
    pool = ThreadPool(processes=8)
    print(list(zip(imgs_list_path,[output_path]*len(imgs_list_path))))
    
    pool.starmap(save_img,zip(imgs_list_path,[output_path]*len(imgs_list_path)))

    pool.close()
    pool.join()
    end_time=time.time()
    print('use time=',end_time-start_time)

三.共享变量 

import numpy as np
from multiprocessing import shared_memory
from multiprocessing import Process
from multiprocessing.managers import SharedMemoryManager
import time
import glob
import os
import shutil

smm = SharedMemoryManager()
smm.start()
screen_img = np.zeros((480, 640, 3), dtype=np.uint8)
share_screen_img = smm.SharedMemory(screen_img.nbytes)


def change(name):
    a = np.array([0, 0, 0, 0, 0, 0])
    existing_shm = shared_memory.SharedMemory(name=name)
    b = np.ndarray((6, ), dtype=np.int64, buffer=existing_shm.buf)
    b[:] = a[:]
    print("changed")


def show(name):
    while True:
        existing_shm = shared_memory.SharedMemory(name=name)
        show_img = np.ndarray((480, 640, 3),
                              dtype=np.uint8,
                              buffer=existing_shm.buf)
        print('show_img:', show_img.sum())
        time.sleep(0.30)


if __name__ == '__main__':
    tmp = np.ndarray(screen_img.shape,
                     dtype=screen_img.dtype,
                     buffer=share_screen_img.buf)
    print('init tmp:', tmp.sum())
    # p1 = Process(target=change, args=(sm.name, ))
    p2 = Process(target=show, args=(share_screen_img.name, ))
    p2.start()
    time.sleep(2)
    tmp[:] = np.ones((480, 640, 3), dtype=np.uint8)
    # p1.join()
    # print('final b:', b)
    p2.join()

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,我明白了您的要求。以下是示例代码: ```python import asyncio from multiprocessing import Pool async def process_item(item): # 处理单个item的函数 return item * 2 async def process_list_async(lst): coroutines = [] for item in lst: coroutines.append(process_item(item)) results = await asyncio.gather(*coroutines) return results def process_list_sync(lst): pool = Pool() results = pool.map(process_item, lst) return results if __name__ == '__main__': # 测试数据 test_list = [1, 2, 3, 4, 5] # 使用协程并发处理列表 loop = asyncio.get_event_loop() async_results = loop.run_until_complete(process_list_async(test_list)) # 使用多进程并发处理列表 sync_results = process_list_sync(test_list) print("Async results:", async_results) print("Sync results:", sync_results) ``` 这段代码演示了如何使用Python的协程和多进程实现列表的并发处理,并返回处理结果。其中,`process_item`是一个处理单个元素的函数,在异步模式下通过添加协程实现异步并发处理。而在多进程模式下,使用Python的`multiprocessing.Pool`实现了多进程并发处理。最后,使用测试数据对两种模式的处理结果进行比较。 ### 回答2: Python中可以使用多进程和协程来实现并发处理列表并返回的示例。 下面介绍一个使用Python多进程和协程实现并发处理列表的简单示例: ```python import multiprocessing import asyncio def process_item(item): # 在这里实现对列表中每个元素的处理逻辑 # ... return processed_item # 返回处理后的结果 def process_list(items): # 使用多进程并发处理列表中的每个元素 with multiprocessing.Pool() as pool: processed_items = pool.map(process_item, items) return processed_items async def process_item_coroutine(item): # 在这里实现对列表中每个元素的处理逻辑 # ... return processed_item # 返回处理后的结果 async def process_list_coroutine(items): # 使用协程来并发处理列表中的每个元素 processed_items = await asyncio.gather(*(process_item_coroutine(item) for item in items)) return processed_items # 示例使用 if __name__ == "__main__": items = [1, 2, 3, 4, 5] # 待处理的列表 # 使用多进程并发处理列表 processed_items = process_list(items) print("使用多进程并发处理列表的结果:", processed_items) # 使用协程并发处理列表 loop = asyncio.get_event_loop() processed_items_coroutine = loop.run_until_complete(process_list_coroutine(items)) print("使用协程并发处理列表的结果:", processed_items_coroutine) ``` 上述示例中,`process_item` 是用来处理列表中的每个元素的函数,`process_list` 是使用多进程并发处理列表的函数。另外,`process_item_coroutine` 是使用协程来处理列表中的每个元素的函数,`process_list_coroutine` 是使用协程来并发处理列表的函数。 在示例中,使用多进程并发处理列表时,使用 `multiprocessing.Pool()` 来创建一个进程池,并使用 `pool.map()` 方法来映射处理函数到列表中的每个元素,返回处理后的结果。 而使用协程来并发处理列表时,使用 `asyncio.gather()` 方法来同时运行多个协程,并等待它们都执行完成后返回结果。 示例程序中,输出了使用多进程和协程并发处理列表的结果。可以根据实际情况选择使用多进程还是协程来实现并发处理列表。 ### 回答3: Python中可以通过多进程和协程来实现并发处理列表并返回结果。 多进程是指使用多个进程同时处理任务。在Python中,可以使用`multiprocessing`模块来创建和管理多个进程。具体实现步骤如下: 1. 定义一个需要处理的任务函数,如`process_item(item)`,用于处理列表中的每个元素。 2. 将需要处理的列表分割成多个子列表,使每个子列表可以由一个独立的进程处理。 3. 使用`multiprocessing.Pool()`创建一个进程池。 4. 使用`pool.map(process_item, sub_list)`方法将任务函数和子列表传递给进程池,实现并发处理。 5. 使用`pool.close()`关闭进程池,防止新的任务提交到进程池。 6. 使用`pool.join()`等待所有进程完成任务。 7. 获取处理结果。 协程是一种轻量级的线程,可以在同一个线程中实现多个任务的切换执行。在Python中,可以使用`asyncio`模块来创建和管理协程。具体实现步骤如下: 1. 定义一个协程函数,如`async def process_item(item)`,用于处理列表中的每个元素。 2. 使用`asyncio.gather(*[process_item(item) for item in item_list])`将所有的协程任务收集起来。 3. 使用`await`关键字等待所有协程任务执行完成,并获取结果。 以下是示例代码: 使用多进程实现并发处理列表: ```python import multiprocessing def process_item(item): # 处理单个元素的逻辑 result = ... return result item_list = [...] # 需要处理的列表 # 将列表分割成子列表 chunk_size = len(item_list) // multiprocessing.cpu_count() sub_lists = [item_list[i:i+chunk_size] for i in range(0, len(item_list), chunk_size)] # 创建进程池 pool = multiprocessing.Pool() # 并发处理子列表 results = [] for sub_list in sub_lists: results += pool.map(process_item, sub_list) # 关闭进程池 pool.close() pool.join() # 处理结果 print(results) ``` 使用协程实现并发处理列表: ```python import asyncio async def process_item(item): # 处理单个元素的逻辑 result = ... return result item_list = [...] # 需要处理的列表 # 创建协程任务 coroutines = [process_item(item) for item in item_list] # 并发执行协程任务 loop = asyncio.get_event_loop() results = loop.run_until_complete(asyncio.gather(*coroutines)) # 处理结果 print(results) ``` 以上是使用多进程和协程实现并发处理列表并返回结果的示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值