当前位置: 首页 > news >正文

同步、异步无障碍:Python异步装饰器指南

一、引言

Python异步开发已经非常流行了,一些主流的组件像MySQL、Redis、RabbitMQ等都提供了异步的客户端,再处理耗时的时候不会堵塞住主线程,不但可以提高并发能力,也能减少多线程带来的cpu上下文切换以及内存资源消耗。但在业务开发的时候一些第三方库没有异步的处理方式,例如OSS、CV、其他第三方提供的SDK以及自己封装的函数有耗时等,此时还是需要借助线程来加速,再异步中就不会堵塞主线程,因此封装一个异步装饰器可以更好的处理异步,让代码更简洁。

二、功能分析

  1. 支持同步函数使用线程加速

  2. 异、同步函数需支持 await 语法等待返回结果

  3. 异、同步函数需支持后台任务,无需等待

同步函数使用线程加速

同步函数使用线程,这还是挺简单的使用,内置库的 threading.Thread 就可以实现

import time
import threadingdef task1(name):print(f"Hello {name}")time.sleep(1)print(f"Completed {name}")t1 = threading.Thread(target=task1, args=("hui",))
t2 = threading.Thread(target=task1, args=("wang",))t1.start()
t2.start()t1.join()
t2.join()>>> out
Hello hui
Hello wang
Completed hui
Completed wang
  • start()方法用于启动线程执行函数。
  • join()方法用于等待线程执行结束。

但这样直接开线程的方式比较暴力,也不太好管理,因此可以想到线程池,进行线程复用与管理。Python内置的 concurrent.futures 模块提供了线程池和进程池的实现与封装。

import time
from concurrent.futures import ThreadPoolExecutordef task2(name):print(f"Hello {name}")time.sleep(1)return f"Completed {name}"with ThreadPoolExecutor(max_workers=2) as executor:future1 = executor.submit(task2, "hui")future2 = executor.submit(task2, "zack")print("ret1", future1.result())
print("ret2", future2.result())>>> out
Hello hui
Hello zack
ret1 Completed hui
ret2 Completed zack

异、同步函数需支持 await 语法

异、同步函数需支持 await 语法等待返回结果,异步函数本身就支持 await语法,这里主要是实现同步函数支持

await 语法,在python中可以await语法的对象有如下几大类:

  1. 协程对象(coroutine):定义了__await__方法的对象,异步框架中的协程函数都是此类型。
  2. 任务对象(Task):封装了协程的对象, 如 asyncio 中的 Task, trio中的Task。
  3. Future对象:表示异步操作结果的对象, 如 concurrent.futures.Future。
  4. 协程装饰器封装的对象:一些装饰器可以将普通函数或对象包装成可await的对象,如@asyncio.coroutine。

综上,凡是实现了__await__魔术方法的对象或者封装了协程/任务的对象,都可以被await,await会自动把对象交给事件循环运行,等待其完成。

常见的可await对象包括协程函数、任务对象、Future、被@coroutine装饰的函数等,这可以使异步代码更简洁。await对象可以暂停当前协程,等待异步操作完成后再继续执行。

import asyncioasync def coro_demo():print("await coroutine demo")async def task_demo():print("await task demo")async def coro():print("in coro task")# 创建 Task 对象task = asyncio.create_task(coro())await taskasync def future_demo():print("await future demo")future = asyncio.Future()await future# 这个装饰器已经过时
@asyncio.coroutine
def coro_decorated_demo():print("await decorated function demo")async def main():await coro_demo()await task_demo()await future_demo()await coro_decorated_demo()if __name__ == '__main__':asyncio.run(main())>>> out 
DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" insteaddef coro_decorated_demo():await coroutine demo
await task demo
in coro task
await future demo

这个 @asyncio.coroutine 协程装饰器已经过时了,都是使用 async、await 语法替代。

下面是实现 __await__ 方法的demo

import asyncioclass AsyncDownloader:def __init__(self, url):self.url = urlself.download_ret = Nonedef __await__(self):print(f'Starting download of {self.url}')loop = asyncio.get_event_loop()future = loop.run_in_executor(None, self.download)yield from future.__await__()return selfdef download(self):print(f'Downloading {self.url}...')# 模拟下载过程import timetime.sleep(2)self.download_ret = f'{self.url} downloaded ok'async def main():print('Creating downloader...')downloader = AsyncDownloader('https://www.ithui.top/file.zip')print('Waiting for download...')downloader_obj = await downloaderprint(f'Download result: {downloader_obj.download_ret}')if __name__ == '__main__':asyncio.run(main())>>> out
Creating downloader...
Waiting for download...
Starting download of https://www.ithui.top/file.zip
Downloading https://www.ithui.top/file.zip...
Download result: https://www.ithui.top/file.zip downloaded ok    

用 yield from 来迭代 future对象(符合__await__逻辑),并在结束时return self

异、同步函数需支持后台任务

异步、后台任务的好处与场景

  1. 减少主程序的等待时间

    异步函数可以通过后台任务的方式执行一些耗时操作,如IO操作、网络请求等,而主程序无需等待这些操作完成,可以继续执行其他任务,从而减少程序总体的等待时间。

  2. 提高程序响应性能

    后台任务的异步执行,可以避免主程序被长时间阻塞,从而改善程序的整体响应性能。用户无需长时间等待才能得到响应。

  3. 解决IO密集型任务阻塞问题

    对于网络、文件IO等密集型任务,使用同步执行可能会导致长时间阻塞,而异步后台任务可以很好地解决这个问题,避免资源浪费。

  4. 良好的用户体验

    后台任务的异步处理,给用户的感觉是多个任务同时在执行,实际上CPU在切换处理,这相比线性等待任务完成,可以提供更好的用户体验。

  5. 适用于不需要实时结果的任务

    邮件发送、数据批处理、文件处理等不需要用户即时等待结果的任务非常适合通过异步方式在后台完成。

在python中同异步函数实现后台任务

  • 异步函数可以通过 asyncio.create_task 方法实现后台任务

  • 同步函数可以通过线程、线程池来实现

import asyncio
import time
from threading import Thread
from concurrent.futures import ThreadPoolExecutorasync def async_bg_task():print('async bg task running')await asyncio.sleep(3)print('async bg task completed')def sync_bg_task():print('sync bg task running')time.sleep(3)print('sync bg task completed')async def main():print('Starting main program')# 异步函数的后台任务asyncio.create_task(async_bg_task())# 同步函数的后台任务# with ThreadPoolExecutor() as executor:#     executor.submit(sync_bg_task)# Thread(target=sync_bg_task).start()loop = asyncio.get_running_loop()loop.run_in_executor(executor=ThreadPoolExecutor(), func=sync_bg_task)print('Main program continues')await asyncio.sleep(5)if __name__ == '__main__':asyncio.run(main())>>> ThreadPoolExecutor out
Starting main program
sync bg task running
sync bg task completed
Main program continues
async bg task running
async bg task completed>>> Thread out
Starting main program
sync bg task running
Main program continues
async bg task running
sync bg task completed
async bg task completed>>> run_in_executor out
Starting main program
sync bg task running
Main program continues
async bg task running
async bg task completed
sync bg task completed

看输出结果可以发现在同步函数使用直接使用线程池 ThreadPoolExecutor 执行还是堵塞了主线程,然后 Thread 没有,通过 loop.run_in_executor 也不会阻塞。后面发现 是 with 语法导致的堵塞,with 的根本原因就是它会等待线程池内的所有线程任务完成并回收,所以主线程必须等同步函数结束后才能继续。一开始我还一以为是线程池使用了主线程的线程后面打印线程名称看了下不是,然后调试下就发现了with的问题。

import asyncio
import time
import threading
from concurrent.futures import ThreadPoolExecutorasync def async_bg_task():print(f"async_bg_task In thread: {threading.current_thread().name}")print('async bg task running')await asyncio.sleep(3)print('async bg task completed')def sync_bg_task(num):print(f"sync_bg_task{num} In thread: {threading.current_thread().name}")print(f'sync bg task{num} running')time.sleep(3)print(f'sync bg task{num} completed')async def main():print('Starting main program')# 异步函数的后台任务asyncio.create_task(async_bg_task())# 同步函数的后台任务thread_pool = ThreadPoolExecutor()# with thread_pool as pool:#     for i in range(5):#         pool.submit(sync_bg_task, i)for i in range(5):thread_pool.submit(sync_bg_task, i)threading.Thread(target=sync_bg_task, args=["thread"]).start()loop = asyncio.get_running_loop()loop.run_in_executor(ThreadPoolExecutor(), sync_bg_task, "loop.run_in_executor")print('Main program continues')print(f"Main program In thread: {threading.current_thread().name}")await asyncio.sleep(5)if __name__ == '__main__':asyncio.run(main())

三、具体封装实现

import asyncio
from concurrent.futures import ThreadPoolExecutor, Executordef run_on_executor(executor: Executor = None, background: bool = False):"""异步装饰器- 支持同步函数使用 executor 加速- 异步函数和同步函数都可以使用 `await` 语法等待返回结果- 异步函数和同步函数都支持后台任务,无需等待Args:executor: 函数执行器, 装饰同步函数的时候使用background: 是否后台执行,默认FalseReturns:"""def _run_on_executor(func):@functools.wraps(func)async def async_wrapper(*args, **kwargs):if background:return asyncio.create_task(func(*args, **kwargs))else:return await func(*args, **kwargs)@functools.wraps(func)def sync_wrapper(*args, **kwargs):loop = asyncio.get_event_loop()task_func = functools.partial(func, *args, **kwargs)    # 支持关键字参数return loop.run_in_executor(executor, task_func)# 异步函数判断wrapper_func = async_wrapper if asyncio.iscoroutinefunction(func) else sync_wrapperreturn wrapper_funcreturn _run_on_executor

封装成了带参数的装饰器

  • executor: 函数执行器, 装饰同步函数的时候使用

    • 可以传递指定的线程池,默认None 根据系统cpu核心数动态创建线程的数量
  • background: 用于标识是否后台执行,默认False

    • 有点诟病同步函数的后台任务没有用到这个参数而是使用 await 语法控制,但在使用装饰器时候可以起到后台任务标识作用,别人一看有这个参数就知道是后台任务就不用细看函数业务逻辑
    • 后续再看看怎么优化,大家有没有比较好建议
  • loop.run_in_executor(executor, task_func) 方法不支持关键字参数的传递,故而采用 task_func = functools.partial(func, *args, **kwargs) ,来构造一个不带参数的函数就可以方便使用了

测试demo

import asyncio
import time
from concurrent.futures import ThreadPoolExecutorfrom py_tools.decorators.base import run_on_executor
from loguru import loggerthread_executor = ThreadPoolExecutor(max_workers=3)@run_on_executor(background=True)
async def async_func_bg_task():logger.debug("async_func_bg_task start")await asyncio.sleep(1)logger.debug("async_func_bg_task running")await asyncio.sleep(1)logger.debug("async_func_bg_task end")return "async_func_bg_task ret end"@run_on_executor()
async def async_func():logger.debug("async_func start")await asyncio.sleep(1)logger.debug("async_func running")await asyncio.sleep(1)return "async_func ret end"@run_on_executor(background=True, executor=thread_executor)
def sync_func_bg_task():logger.debug("sync_func_bg_task start")time.sleep(1)logger.debug("sync_func_bg_task running")time.sleep(1)logger.debug("sync_func_bg_task end")return "sync_func_bg_task end"@run_on_executor()
def sync_func():logger.debug("sync_func start")time.sleep(1)logger.debug("sync_func running")time.sleep(1)return "sync_func ret end"async def main():ret = await async_func()logger.debug(ret)async_bg_task = await async_func_bg_task()logger.debug(f"async bg task {async_bg_task}")logger.debug("async_func_bg_task 等待后台执行中")loop = asyncio.get_event_loop()for i in range(3):loop.create_task(async_func())ret = await sync_func()logger.debug(ret)sync_bg_task = sync_func_bg_task()logger.debug(f"sync bg task {sync_bg_task}")logger.debug("sync_func_bg_task 等待后台执行")await asyncio.sleep(10)if __name__ == '__main__':asyncio.run(main())

测试详细输出

async_func start
async_func running
async_func ret endasync bg task <Task pending name='Task-2' coro=<async_func_bg_task() running at ...
sync_func start
async_func_bg_task start
async_func start
async_func start
async_func startsync_func running
async_func_bg_task running
async_func running
async_func running
async_func runningasync_func_bg_task end
sync_func ret endsync_func_bg_task start
sync bg task <Future pending cb=[_chain_future.<locals>._call_check_cancel() at ...
sync_func_bg_task 等待后台执行
sync_func_bg_task running
sync_func_bg_task end

四、源代码

HuiDBK/py-tools: 打造 Python 开发常用的工具,让Coding变得更简单 (github.com)

---------------------------END---------------------------

题外话

“不是只有程序员才要学编程?!”

认真查了一下招聘网站,发现它其实早已变成一项全民的基本技能了。

连国企都纷纷要求大家学Python!
在这里插入图片描述

世界飞速发展,互联网、大数据冲击着一切,各行各业对数据分析能力的要求越来越高,这便是工资差距的原因,学习编程顺应了时代的潮流。

在这个大数据时代,从来没有哪一种语言可以像Python一样,在自动化办公、爬虫、数据分析等领域都有众多应用。

更没有哪一种语言,语法如此简洁易读,消除了普通人对于“编程”这一行为的恐惧,从小学生到老奶奶都可以学会。

《2020年职场学习趋势报告》显示,在2020年最受欢迎的技能排行榜,Python排在第一。
在这里插入图片描述

它的角色类似于现在Office,成了进入职场的第一项必备技能。

如果你也想增强自己的竞争力,分一笔时代的红利,我的建议是,少加点班,把时间腾出来,去学一学Python。

因为,被誉为“未来十年的职场红利”的Python,赚钱、省钱、找工作、升职加薪简直无所不能!

目前,Python人才需求增速高达**174%,人才缺口高达50万,**部分领域如人工智能、大数据开发, 年薪30万都招不到人!在这里插入图片描述

感兴趣的小伙伴,赠送全套Python学习资料,包含面试题、简历资料等具体看下方。

👉CSDN大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击)

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。

img
img

二、Python必备开发工具

工具都帮大家整理好了,安装就可直接上手!img

三、最新Python学习笔记

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。

img

四、Python视频合集

观看全面零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

img

五、实战案例

纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。img

六、面试宝典

在这里插入图片描述

在这里插入图片描述

简历模板在这里插入图片描述

如有侵权,请联系删除。

相关文章:

同步、异步无障碍:Python异步装饰器指南

一、引言 Python异步开发已经非常流行了&#xff0c;一些主流的组件像MySQL、Redis、RabbitMQ等都提供了异步的客户端&#xff0c;再处理耗时的时候不会堵塞住主线程&#xff0c;不但可以提高并发能力&#xff0c;也能减少多线程带来的cpu上下文切换以及内存资源消耗。但在业务…...

CodeSite for .NET Crack

CodeSite for .NET Crack CodeSite for.NET与Visual Studio集成&#xff0c;通过实时查看器日志记录系统提供对代码执行的更深入了解&#xff0c;该系统有助于在本地或远程执行代码时快速查找问题。超越传统的断点调试&#xff0c;在应用程序继续运行时记录应用程序的执行&…...

基于IMX6ULLmini的linux裸机开发系列九:时钟控制模块

时钟控制模块 核心 4个层次配置芯片时钟 晶振时钟 PLL与PFD时钟 PLL选择时钟 根时钟/外设时钟 系统时钟来源 RTC时钟源&#xff1a;32.768KHz 系统时钟&#xff1a;24MHz&#xff0c;作为芯片的主晶振使用 PLL和PFD倍频时钟 7路锁相环电路&#xff08;每个锁相环电路…...

【数据结构与算法】1. 绪论

1. 绪论 1.1 数据结构 1.1.1 数据结构的基本概念 1.1.2 数据结构的三要素 数据结构三要素&#xff1a; 逻辑结构 划分方法一&#xff1a; 线性结构&#xff1a;线性表、栈、队列、串非线性结构&#xff1a;树、图 划分方法二&#xff1a; 集合结构线性结构树形结构网状&…...

2023年京东儿童智能手表行业数据分析(京东销售数据分析)

儿童消费市场向来火爆&#xff0c;儿童智能手表作为能够实现定位导航&#xff0c;信息通讯&#xff0c;SOS求救&#xff0c;远程监听&#xff0c;智能防丢等多功能的智能可穿戴设备&#xff0c;能够通过较为精准的定位功能和安全防护能力保障儿童的安全&#xff0c;因而广受消费…...

数据结构(6)

2-3查找树 2-结点&#xff1a;含有一个键(及其对应的值)和两条链&#xff0c;左链接指向2-3树中的键都小于该结点&#xff0c;右链接指向的2-3树中的键都大于该结点。 3-结点&#xff1a;含有两个键(及其对应的值)和三条链&#xff0c;左链接指向的2-3树中的键都小于该结点&a…...

C++学习|CUDA安装和配置

CUDA安装和配置 Windows下安装CUDAVS项目配置CUDA Windows下安装CUDA 第一步&#xff1a;先看自己NIVIDIA显卡适合什么版本的CUDA。打开电脑的“NIVIDIA控制面板”->系统信息->组件。会看到我的显卡驱动最高支持的CUDA版本是11.4.56。 第二步&#xff1a;去CUDA官网&…...

3.若依前后端分离版开发用户自定义配置表格功能

一、背景 在项目上线测试的时候&#xff0c;关于同一个界面的表格&#xff0c;不同的用户会出现不同的字段排列需求&#xff0c;有些用户希望把A字段排在最前面&#xff0c;有些用户则希望A字段不显示。针对这种情况&#xff0c;开发一个表格自定义配置的功能&#xff0c;每个…...

【操作系统】24王道考研笔记——第三章 内存管理

第三章 内存管理 一、内存管理概念 1.基本概念 2.覆盖与交换 覆盖技术&#xff1a; 交换技术&#xff1a; 总结&#xff1a; 3.连续分配管理方式 单一连续分配 固定分区分配 动态分区分配 动态分区分配算法&#xff1a; 总结&#xff1a; 4.基本分页存储管理 定义&#xf…...

Spring缓存深入解析:@Cacheable的使用详解

摘要&#xff1a;在本文中&#xff0c;我们将深入研究Spring框架中的Cacheable注解。我们会通过详细的Java示例&#xff0c;探讨如何使用这个功能强大的注解来提升应用程序性能。 一、什么是缓存&#xff1f; 在计算机科学中&#xff0c;缓存是一种存储技术&#xff0c;用于保…...

软件配置安装(破解)--- jdk下载配置

下载jdk 如果有oracle账号的话直接登录下载你想要的版本 不然可以尝试镜像站 HUAWEI镜像&#xff1a;https://repo.huaweicloud.com/java/jdk/ 安装 配置&#xff08;细节&#xff09; 这里的JAVA_HOME就是java的家&#xff0c;也就是解压(或安装)之后的java的目录&#xff…...

idea使用docker生成镜像(打包镜像,导入镜像,导出镜像)

1&#xff1a;先下载安装dockerdesktop&#xff0c;安装成功后 2&#xff1a; 在cmd执行docker -v&#xff0c;查看安装的docker版本 C:\Users\dell>docker -v Docker version 24.0.5, build ced09963&#xff1a;需要启动 dockerdesktop应用&#xff0c;才算启动docker&a…...

wazuh环境配置

目录 一、wazuh的安装 1.1官方仓库安装 1.2虚拟机OVA安装 1.2.1 然后执行下面命令 1.2.2 这里还要下载脚本和config.yml配置文件&#xff0c;用来生成证书​编辑 1.2.3然后编辑config.yml文件&#xff0c;将下面的三个IP地址改为一样的 1.2.4运行./wazuh-certs-tool.sh以…...

【Linux】Linux下常用压缩解压缩指令及选项小结

0x00 前言 版本信息&#xff1a;Ubuntu 18.04.6 LTS 最后更新日期&#xff1a;2023.8.22 0x01 Linux下常用压缩解压缩指令小结 1.gzip指令 gzip file&#xff1a;压缩file文件为file.gz &#xff0c;但是只能压缩文件不能压缩目录&#xff0c;且不保留源文件。若想打包目录…...

香蕉派社区推出带10G SFP+ 端口的Banana Pi BPI-R4 Wifi7开源路由器

香蕉派BPI-R4 根据著名Banana Pi品牌背后的公司Sinovoip提供的初步信息&#xff0c;他们即将推出的Banana Pi BPI-R4路由器板目前正在开发中。与之前的 Banana Pi R3 板相比&#xff0c;这在规格上将有显着提升。这就是我们目前所知道的。 您可以选择 R4 板的两种不同配置。具…...

A 题:震源属性识别模型构建与震级预测 :代码分析:

问题 1&#xff1a; 针对附件 1&#xff5e;8 中的地震波数据&#xff0c;找出一系列合适的指 标与判据&#xff0c;构建震源属性识别模型&#xff0c;进行天然地震事件&#xff08;附件 1&#xff5e;7&#xff09; 与非天然地震事件&#xff08;附件 8&#xff09;的准确区…...

源码分析CompletableFuture使用默认线程池ForkJoinPool的弊端

先说结论&#xff1a; 假如有20CompletableFuture任务并发执行时&#xff0c;都使用默认线程池ForkJoinPool&#xff0c;但cpu的核心数又小于3&#xff0c;那么就会新建20个线程&#xff08;不使用默认线程池了&#xff09;&#xff0c;这20个线程相互竞争cpu资源和内存&#x…...

连接pgsql数据库 sslmode sslrootcert sslkey sslcert 参数的作用

sslmode 参数的作用 sslmode 参数用于指定数据库连接时使用的 SSL 加密模式。SSL&#xff08;Secure Sockets Layer&#xff09;是一种加密协议&#xff0c;用于保护数据在客户端和服务器之间的传输过程&#xff0c;以增加数据传输的安全性。sslmode 参数可以设置不同的值&…...

从零学算法3

3.给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”&#xff0c;所以其长度为 3。 示例 2: 输入: “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”&…...

宠物小程序开发

在当今社会&#xff0c;宠物已成为许多人生活中不可或缺的一部分。宠物市场的持续增长为创业者提供了巨大的商机。然而&#xff0c;作为一个创业者&#xff0c;要在竞争激烈的宠物市场中脱颖而出并不容易。因此&#xff0c;开发一个专属于自己的宠物小程序成为了解决这一难题的…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个对象的状态变化需要自动通知其他对象&#xff0c;比如&#xff1a; 电商平台中&#xff0c;商品库存变化时需要通知所有订阅该商品的用户&#xff1b;新闻网站中&#xff0…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...