首页 > 编程语言 >python基础之并发

python基础之并发

时间:2023-06-21 17:33:41浏览次数:38  
标签:task python 基础 并发 tasks time print import asyncio

一、多线程

示例代码1:简单多线程

import time
import threading


def foo(t):
    print("foo 开始")
    time.sleep(t)
    print("foo 结束")

start = time.time()
t_list = []
for i in range(100):
    t = threading.Thread(target=foo, args=(2,)) # 注意,如果只有一个参数,必须有逗号,表明是一个元组
    t.start()
    t_list.append(t)

for t in t_list:
    t.join()

print(f"耗时{time.time() - start}秒")

示例代码2:互斥锁

import time
import threading

Lock = threading.Lock()


def addNum():
    global num  # 在每个线程中都获取这个全局变量
    # 上锁
    Lock.acquire()
    t = num - 1
    time.sleep(0.0001)
    num = t
    Lock.release()
    # 放锁


num = 100  # 设定一个共享变量
thread_list = []
for i in range(100):
    t = threading.Thread(target=addNum)
    t.start()
    thread_list.append(t)
for t in thread_list:  # 等待所有线程执行完毕
    t.join()
print('Result: ', num)

示例代码3:线程池

import time
from concurrent.futures import ThreadPoolExecutor


def task(i):
    print(f'任务{i}开始!')
    time.sleep(i)
    print(f'任务{i}结束!')
    return i

start = time.time()
pool = ThreadPoolExecutor(3)

future_list = []
for i in range(1, 4):
    # 线程池技术实现异步,完成并发
    future = pool.submit(task, i)  # future对象内包含很多内容,如result()为返回值
    future_list.append(future)

pool.shutdown()  # 阻塞
print(f"耗时{time.time() - start}")

print(future_list)
print([future.result() for future in future_list]) # 打印返回值列表

总结

使用线程池来执行线程任务的步骤如下:

  1. 调用 ThreadPoolExecutor 类的构造器创建一个线程池。
  2. 定义一个普通函数作为线程任务。
  3. 调用 ThreadPoolExecutor 对象的 submit() 方法来提交线程任务。
  4. 当不想提交任何任务时,调用 ThreadPoolExecutor 对象的 shutdown() 方法来关闭线程
    池。

二、多进程

示例代码:

import multiprocessing
# multiprocessing.Process拥有和threading.Thread()同样的API
import time


def foo(t):
    print(f"任务{t} 开始")
    time.sleep(t)
    print(f"任务{t} 结束")


# 多进程主程序必须写在__main__内
if __name__ == '__main__':
    start = time.time()

    # 3 基于多进程的并发
    t_list = []
    for i in range(1, 6):
        t = multiprocessing.Process(target=foo, args=(i,))
        t.start()
        t_list.append(t)

    for t in t_list:
        t.join()

    print(f"耗时{time.time() - start}秒")
	

三、协程 asyncio

示例代码1:

import asyncio
import time


async def task(i):
    print(f"任务{i}启动")
    await asyncio.sleep(i)
    print(f"任务{i}结束")


start = time.time()
# 创建事件循环对象
loop = asyncio.get_event_loop()
# 构建协程对象列表
tasks = [task(1), task(2), task(3)]  # task(1):协程对象coroutine object
print("tasks[0]:", tasks[0])
# 启动运行
loop.run_until_complete(asyncio.wait(tasks))  # 阻塞等待所有的协程结束
print("cost timer:", time.time() - start)

示例代码2: 获取异步任务的结果,回调函数

import asyncio
import time


async def foo(i):
    print(f"任务{i}启动")
    await asyncio.sleep(i)
    print(f"任务{i} {i}秒结束")
    return i * i


def task2callback(ret):
    print("异步任务2的结果:", ret.result())


start = time.time()
# 创建事件循环对象
loop = asyncio.get_event_loop()
# 构建任务对象列表
tasks = [
    asyncio.ensure_future(foo(1)),
    asyncio.ensure_future(foo(2)),
    asyncio.ensure_future(foo(3)),
]  # task(1):asyncio.Task

for task in tasks:
	task.add_done_callback(task2callback)

# 启动运行
loop.run_until_complete(asyncio.wait(tasks))  # 阻塞等待所有的协程结束

for task in tasks:
    print(task.done(), task.result())

print("cost timer:", time.time() - start)

示例代码3:gather可以返回任务返回值

import asyncio
import time


async def foo(i):
    print(f"任务{i}启动")
    await asyncio.sleep(i)
    print(f"任务{i} {i}秒结束")
    return i * i


async def main():
    # 构建任务对象列表
    tasks = [
        asyncio.create_task(foo(1)),
        asyncio.create_task(foo(2)),
        asyncio.create_task(foo(3)),
    ]

    # 方式1
    # tasks[0].add_done_callback(lambda ret: print(ret.result()))
    #
    # await asyncio.wait(tasks)  # 阻塞
    #
    # for task in tasks:
    #     print(task.done(), task.result())

    # 方式2
    rets = await asyncio.gather(*tasks) # gather必须传入多个task对象,不能传入列表
    print(rets)


start = time.time()
asyncio.run(main())
print("cost timer:", time.time() - start)

示例代码4: aiohttp

import aiohttp
import asyncio


async def main():
    async with aiohttp.ClientSession() as session:
        async with session.get("http://httpbin.org/headers") as response:
            print(await response.text())


asyncio.run(main())

示例代码5:aiohttp 和 aiofiles

import asyncio
import aiohttp
import aiofiles

urls = ["https://img.lianzhixiu.com/uploads/allimg/202109/9999/d1eeaa0450.jpg",
        "https://img.lianzhixiu.com/uploads/allimg/202109/9999/6747451f08.jpg",
        "https://img.lianzhixiu.com/uploads/allimg/202108/9999/88abd53cc1.jpg"
        ]


async def aioDownload(url):
    # 发送请求
    # 得到图片内容
    # 保存到文件
    print("开始下载")
    name = url.rsplit("/", 1)[1]  # 从右边切一次,得到[1]位置的内容
    async with aiohttp.ClientSession() as session:  # 相当于requests
        async with session.get(url) as resp:  # 相当于resp = requests.get()
            # 请求回来了,aiofiles写入文件,
            async with aiofiles.open(name, mode='wb') as f:  # 创建文件
                await f.write(await resp.content.read())  # 读取内容是异步的,需要await挂起,resp.text()

    print("下载完成")


async def main():
    # 准备异步协程对象列表
    tasks = []

    for url in urls:
        task = asyncio.create_task(aioDownload(url))
        tasks.append(task)

    await asyncio.wait(tasks)


"""
========================================
主函数功能测试
========================================
"""
if __name__ == '__main__':
    # 一次性启动多个任务
    # asyncio.run(main())

    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

标签:task,python,基础,并发,tasks,time,print,import,asyncio
From: https://www.cnblogs.com/yuan-qi/p/17496794.html

相关文章

  • python在if判断语句中对于0和None的处理
    情景:我在访问一个字典的key,但是我不知道这个key有没有,或者有,我也不知道value取值多少,即dict1.get(key)有可能输出None,也有可能输出0如果我对这个key进行判断,例如:ifdict1.get(key)这种判断,可能对于None和0的条件都是一样的,因此,如果我只是想判断是否存在这个key,我需要ifdict1......
  • Linux下卸载python,并安装pyenv管理python版本
    一、卸载已安装的python版本查找已安装的Python3版本:运行以下命令以获取已安装的Python3版本列表:dpkg-l|greppython3找到列出所有以python3开头的已安装软件包。可能会有多个Python3相关的软件包,因此仔细检查输出的内容。2.卸载Python3软件包:从步骤1......
  • python字典访问不存在的key
    当你使用一个不存在的键(key)去访问一个Python字典(dict)时,会触发一个KeyError异常。这是Python提供的一种机制,用于指示你正在尝试访问一个字典中不存在的键。以下是一个简单的示例,演示了当使用一个不存在的键去访问字典时会发生的情况:my_dict={"apple":3,"banana":6,"orange......
  • 供应链协同——企业全球供应链可持续发展的基础
    供应链协同,是真正提高企业全球供应链透明度、韧性和可持续发展的基础协同能力。整个供应链协同能力包括六个模块:库存协同:有没有货,在海外的库存和国内的库存信息协同,形成高效的调货;计划协同:基于这些信息能够快速地滚动和预警;订单协同:端到端数字转型的能力,保障供应链稳定,抵御干扰;运输......
  • Python中的pickle模块:对象序列化与反序列化
    在Python中,对象的序列化和反序列化是一项常见的任务。pickle模块提供了一种简单且强大的方法来实现对象的序列化和反序列化,使得开发者能够方便地将复杂的Python对象转化为字节流并在需要时重新还原。本文将详细介绍pickle模块的使用方法和原理,并探讨其在数据持久化和跨进程通信中......
  • 神经网络基础知识与实现
    目录神经网络是人工智能领域中的一个重要概念,它是指一种模拟人脑神经元的计算方法。神经网络通过从大量数据中学习,来预测未来的状态或执行特定的任务。本文将介绍神经网络的基础知识与实现,包括神经网络的基本概念、技术原理、实现步骤以及示例与应用。同时,本文还将探讨神经网络的性......
  • 软件测试|超好用超简单的Python GUI库——tkinter(四)
    前言之前我们介绍了label控件,本篇文章我们将介绍button控件。Button控件是Tkinter中常用的窗口部件之一,同时也是实现程序与用户交互的主要控件。通过用户点击按钮的行为来执行回调函数,是Button控件的主要功用。首先自定义一个函数或者方法,然后将函数与按钮关联起来,最后,当用......
  • 软件测试|超好用超简单的Python GUI库——tkinter(五)
    前言在之前,我们介绍了tkinter的button控件,label控件,今天我们介绍一下entry控件,entry控件我们可以理解为界面的内容输入框,实现GUI界面与用户的信息交互,最典型的场景就是我们在登录时需要输入的账号密码。获取更多技术资料,请点击!Entry控件使用起来非常简单,下面对该控件做简单的......
  • 三秒看懂Python yield
    业务场景:一个FastAPI构建的网关,数据进来时立即给予一次响应,表示:“收到,我已开始执行。”,然后分发任务另起一个线程异步执行。原本代码写的在异步里又起了一个异步等任务执行,这样不影响下面的return立刻响应。逻辑看起很繁琐,那有没有办法,能让函数在"return":“收到”之后,继续执行呢?......
  • python如何用openpyxl 创建表格,写入数据
    1.安装openpyxl库,可以选择豆瓣源,直接可执行,是一次性的.不需要设置.pipinstallopenpyxl-ihttp://pypi.douban.com/simple--trusted-hostpypi.douban.com 2.我们这里创建一个表(不是打开本地),并插入数据'sandx'是设置表中单表sheet的标题栏.插入数......