[python] 轻量级定时任务调度库schedule使用指北

schedule是一款专为简化定时任务调度而设计的Python库,它通过直观的语法降低了周期性任务的实现门槛。作为进程内调度器,它无需额外守护进程,轻量且无外部依赖,适合快速搭建自动化任务。不过,该库在功能完整性上有所取舍,目前暂不支持断点续传、亚秒级精度控制以及多任务并行执行等复杂场景。

schedule库的官方仓库地址见:schedule,schedule库的官方文档见:schedule-doc。

schedule库支持在Python 3.7及以上版本的环境中运行,schedule库的安装命令如下:

pip install schedule

文章目录

  • 1 使用入门
    • 1.1 基础使用
      • 1.1.1 相对调用
      • 1.1.2 绝对调用
    • 1.2 进阶使用
      • 1.2.1 调用程序管理
      • 1.2.2 调用时间管理
      • 1.2.3 调用运行方式管理
  • 2 参考

1 使用入门

1.1 基础使用

1.1.1 相对调用

schedule库通过创建调度器,设置时间单位,注册待调用函数,返回任务对象实现任务周期调用。例如:

# 每3秒执行一次任务
schedule.every(3).seconds.do(job)

这种调用方式是相对调用方式,任务执行间隔是相对于当前时间点计算的。例如17:59:01创建调度器,下一次执行时间为17:59:04

示例代码如下:

import schedule  
import time      
from datetime import datetimedef get_now_time():now = datetime.now()now = now.strftime("%Y-%m-%d %H:%M:%S")return nowdef job():"""定时执行的任务函数"""print(f"{get_now_time()} I'm working...") print(f"调度器创建时间:{get_now_time()}")
# 调度器返回job对象
schedule_job = schedule.every(3).seconds.do(job)print(f"调度器下一次运行时间:{schedule_job.next_run}")# 任务调度主循环
# 持续检查是否有待执行的任务
while True:schedule.run_pending()  # 检查并执行待执行的任务time.sleep(1)          # 休眠1秒避免CPU占用过高# 为None就是没运行print(f"调度器上一次运行时间:{schedule_job.last_run}")print(f"调度器下一次运行时间:{schedule_job.next_run}")

其他相对时间间隔调用代码如下:

# 每3分钟执行一次任务
schedule.every(3).minutes.do(job)
# 每小时执行一次任务
schedule.every().hours.do(job)
# 每3天执行一次任务
schedule.every(3).days.do(job)
# 每3周执行一次任务
schedule.every(3).weeks.do(job)
# 每周一执行任务
schedule.every().monday.do(job)

1.1.2 绝对调用

schedule可以在相对调用的基础上结合at函数实现绝对时间的调度。例如:

schedule.every(3).hours.at("11:16").do(job)

上述代码可拆解为:

job1 = schedule.every(3).hours
job2 = job1.at("11:16").do(job)

此处的job1基于当前调用器创建时间(例如18:34:54),以小时为间隔粒度进行设定,即每间隔3小时执行一次任务,因此下一次任务执行时间为21:34:54。而at()函数的作用是在job1设定的时间粒度和间隔范围内,具体指定分钟和秒。以job2中的at("11:16")为例,这里的11:16代表分钟和秒。它会在18:34:5421:34:54的时间区间内,定位离21:34:54最近的1116秒时刻,即21:11:16

若按每分钟调用一次任务,可通过at指定固定执行秒数。例如,当创建时间为18:34:54时,下一次执行时间为18:35:16,对应代码如下:

schedule_job = schedule.every().minutes.at(":16").do(job)

at函数的输入范围由设定的时间粒度决定,且仅支持日级、时级、分级三类时间粒度,具体子粒度支持规则如下:

  • 每日任务:支持HH:MM:SS(时分秒)和HH:MM两种格式(HH:MM默认补全为HH:MM:00);
  • 每小时任务:支持MM:SS(分秒)和:MM两种格式(:MM默认补全为MM:00);
  • 每分钟任务:仅支持:SS(秒)格式。

其他绝对时间间隔调用代码如下:

# 基于当前时间,每分钟的16秒执行任务
schedule.every().minutes.at(":16").do(job)
# 基于当前时间,每小时的第23分钟00秒执行任务
schedule.every().hours.at(":23").do(job)
# 基于当前时间,每5小时的第20分30秒执行任务
schedule.every(5).hours.at("20:30").do(job)
# 基于当前时间,每天上午10:30:00执行任务
schedule.every().days.at("10:30").do(job)
# 基于当前时间,每天上午10:30:42执行任务
schedule.every().days.at("10:30:42").do(job)
# 基于当前时间,每天上午12:42(阿姆斯特丹时区)执行任务
schedule.every().days.at("12:42", "Europe/Amsterdam").do(job)
# 基于当前时间,每周三下午1点15分执行任务
schedule.every().wednesday.at("13:15").do(job)

以下示例代码演示了多任务调度场景。作为轻量级任务调度库,schedule会维护任务列表,调用schedule.run_pending()时检查所有任务触发条件,满足条件的任务将按顺序执行。若任务时间冲突,schedule不会主动处理,而是按任务添加顺序依次执行。

import schedule  
import time      
from datetime import datetimedef get_now_time():now = datetime.now()now = now.strftime("%Y-%m-%d %H:%M:%S")return nowdef job():"""定时执行的任务函数"""print(f"{get_now_time()} I'm working...") # 基于当前时间,设置各种定时任务
# 基于当前时间,每分钟的16秒执行任务
schedule.every().minutes.at(":16").do(job)
# 基于当前时间,每小时的第23分钟00秒执行任务
schedule.every().hours.at(":23").do(job)
# 基于当前时间,每5小时的第20分30秒执行任务
schedule.every(5).hours.at("20:30").do(job)
# 基于当前时间,每天上午10:30:00执行任务
schedule.every().days.at("10:30").do(job)
# 基于当前时间,每天上午10:30:42执行任务
schedule.every().days.at("10:30:42").do(job)
# 基于当前时间,每天上午12:42(阿姆斯特丹时区)执行任务
# 需要安装pip install pytz
schedule.every().days.at("12:42", "Europe/Amsterdam").do(job)
# 基于当前时间,每周三下午1点15分执行任务
schedule.every().wednesday.at("13:15").do(job)# 任务调度主循环
# 持续检查是否有待执行的任务
while True:schedule.run_pending()  time.sleep(1)          

1.2 进阶使用

1.2.1 调用程序管理

装饰器调用

可以通过使用@repeat装饰器来调度函数。传递给它一个时间间隔,但省略do函数:

from schedule import every, repeat, run_pending
import time
from datetime import datetimedef get_now_time():now = datetime.now()now = now.strftime("%Y-%m-%d %H:%M:%S")return now@repeat(every(2).seconds)
def job():print(f"{get_now_time()} I'm working...") while True:run_pending()time.sleep(1)

参数传递

在调用时,可以通过do函数传递额外的参数给任务函数:

import schedule
import time
from schedule import every, repeat, run_pending
from datetime import datetimedef get_now_time():now = datetime.now()now = now.strftime("%Y-%m-%d %H:%M:%S")return nowdef job(name, message):print(f"{get_now_time()} {message} {name}") 
# 传递name和message参数
schedule.every(2).seconds.do(job, name='world!', message='hello')@repeat(every().seconds, "code", "good")
def hello(name, message):print(message, name)while True:run_pending()time.sleep(1)

任务取消

若要从调度器中移除任务,可使用schedule.cancel_job(job)方法。

import scheduledef some_task():print('Hello world')job = schedule.every().days.at('12:30').do(some_task)
schedule.cancel_job(job)

任务移除

从任务调用的函数中返回schedule.CancelJob可以将其从调度器中移除,注意以下代码由于有while函数,移除后代码并不会退出:

import schedule
import timedef job_that_executes_once(name):print(f"hello {name}")return schedule.CancelJobschedule.every().minutes.at(':30').do(job_that_executes_once,name="job1")while True:schedule.run_pending()time.sleep(1)

任务批管理

以下代码展示了获取所有运行的任务,同时一次性清除所有任务:

# 导入 schedule 库用于创建和管理定时任务
import schedule# 定义任务函数,接收一个名字参数并打印问候语
def greet(name):print('Hello {}'.format(name))job1 = schedule.every().second.do(greet, name='job1')
schedule.every().second.do(greet, name='job2')# 获取当前所有已注册的定时任务
all_jobs = schedule.get_jobs()
# 打印任务列表(包含任务类型、执行周期、函数名和参数等信息)
print(all_jobs)schedule.every().second.do(greet, name='job3')# 取消job1任务(通过之前保存的任务对象引用)
# 取消后该任务将不再执行
schedule.cancel_job(job1)# 重新获取当前所有已注册的定时任务
all_jobs = schedule.get_jobs()
print(all_jobs)# 清除所有已注册的定时任务
schedule.clear()

标签管理

以下代码展示了如何为任务设置标签,并基于标签挑选和管理任务:

import schedule
import timedef greet(name):print(f"Hello {name}")# 创建带标签的定时任务
schedule.every().days.do(greet, 'Andrea').tag('daily-tasks', 'friend')
schedule.every().hours.do(greet, 'John').tag('hourly-tasks', 'friend')
schedule.every().hours.do(greet, 'Monica').tag('hourly-tasks', 'customer')
schedule.every().days.do(greet, 'Derek').tag('daily-tasks', 'guest')# 获取特定标签的任务
friends = schedule.get_jobs('friend')
print("所有带有friend标签的任务:")
# 取消带有daily-tasks标签的任务
schedule.clear('daily-tasks')for job in friends:print(f"- {job}")# 运行所有待执行的任务
while True:schedule.run_pending()time.sleep(1)

1.2.2 调用时间管理

随机时间

以下代码展示了按随机间隔运行任务的功能:

import schedule
import time
from datetime import datetimedef get_now_time():now = datetime.now()now = now.strftime("%Y-%m-%d %H:%M:%S")return nowdef my_job():print(f"{get_now_time()} hello") # 在1秒到5秒这个闭区间内,随机选择一个间隔时间,周期性地执行指定的任务函数
schedule.every(1).to(5).seconds.do(my_job)while True:schedule.run_pending()time.sleep(1)

截至时间

以下代码展示如何调用until函数设置任务的截止时间,任务在截止时间之后将不再运行。

import schedule
from datetime import datetime, timedelta, time
from datetime import datetimedef get_now_time():now = datetime.now()now = now.strftime("%Y-%m-%d %H:%M:%S")return nowdef job():print(f"{get_now_time()} hello") # 在今天22:30前,每隔1小时执行一次任务
schedule.every(1).hours.until("22:30").do(job)# 在2030-01-01 22:33前,每隔1小时执行一次任务
schedule.every(1).hours.until("2030-01-01 22:33").do(job)# 在接下来的8小时内,每隔1小时执行一次任务
schedule.every(1).hours.until(timedelta(hours=8)).do(job)# 在今天22:33:42前,每隔1小时执行一次任务
schedule.every(1).hours.until(time(22, 33, 42)).do(job)# 在2027-05-17 11:36:20前,每隔5秒执行一次任务
schedule.every(5).seconds.until(datetime(2027, 5, 17, 11, 36, 20)).do(job)# 主循环:持续检查并执行待处理的任务
while True:schedule.run_pending()

获取执行时间

使用schedule.idle_seconds()来获取距离下次任务计划执行的剩余秒数。如果下次计划执行的任务本应在过去执行,返回值为负数。若没有计划任务,则返回None。示例如下:

import schedule
import timedef job():print('你好')schedule.every(2).minutes.do(job)while 1:# n为距离下次执行任务的剩余秒数n = schedule.idle_seconds()print(n)if n is None:# 没有更多任务breakelif n > 0:# 精确睡眠相应的时间time.sleep(n)schedule.run_pending()

1.2.3 调用运行方式管理

任务全部运行

以下代码展示了通过run_all()忽略任务预设的时间安排,立即执行所有已定义的任务。先定义的任务先执行。示例如下:

import schedule
from datetime import datetimedef get_now_time():now = datetime.now()now = now.strftime("%Y-%m-%d %H:%M:%S")return nowdef job_1():print(f"{get_now_time()} job1") def job_2():print(f"{get_now_time()} job2") schedule.every().monday.at("12:40").do(job_1)
schedule.every().tuesday.at("16:40").do(job_2)# 立即运行所有任务一次
schedule.run_all()# 立即运行所有任务,每个任务运行间隔3秒
schedule.run_all(delay_seconds=3)

后台运行

默认情况下,无法在后台运行调度程序。不过,通过创建一个线程,利用该线程在不阻塞主线程的情况下运行任务。以下是实现这一操作的示例:

import threading
import timeimport scheduledef run_continuously(interval=1):"""创建一个后台线程持续运行调度器"""# 创建事件对象用于控制线程停止# Event是事件类,线程间通信的简单机制,有"set"和"clear"两种状态# 初始状态为"clear",通过cease_continuous_run.is_set()判断是否为setcease_continuous_run = threading.Event()class ScheduleThread(threading.Thread):@classmethoddef run(cls):# 在线程启动后循环执行# 只要任务状态不是set,就运行任务while not cease_continuous_run.is_set():# 检查并执行所有待执行的定时任务schedule.run_pending()# 休眠指定间隔时间time.sleep(interval)# 创建并启动调度线程continuous_thread = ScheduleThread()continuous_thread.start()# 返回事件对象用于后续停止线程return cease_continuous_rundef background_job():"""定时执行的后台任务"""print('Hello from the background thread')# 设置定时任务:每秒执行一次background_job函数
schedule.every().second.do(background_job)# 启动后台调度线程并获取停止控制器
stop_run_continuously = run_continuously()# 主线程继续执行其他任务
print("主线程继续执行中...")
time.sleep(5)# 停止后台调度线程
# 将事件对象的内部标志设置为set
stop_run_continuously.set()
print("后台线程已停止")

多任务同时执行

默认情况下,schedule任务调度工具会按顺序逐个执行所有任务。以10秒内执行30个任务为例,从日志中可以看到,这些任务会在这10秒内以串行方式依次执行,如同排队等候处理,而非同时运行。这种设计的核心目的是避免多个任务抢占资源或产生相互干扰,从而确保任务执行的稳定性和可靠性。

若需要实现多个任务并行运行,可通过为每个任务分配独立线程的方式达成,并通过统一队列进行调用。如下所示:

import time
import threading
import schedule
import queue
from datetime import datetime# 获取当前时间并格式化为字符串
def get_now_time():now = datetime.now()now = now.strftime("%Y-%m-%d %H:%M:%S")return now# 定义任务函数,打印当前时间和任务名称
def job(name):print(f"{get_now_time()} {name}")  # 工作线程主函数,负责从队列中获取并执行任务
def worker_main():while True:joo_func,name = jobqueue.get()joo_func(name)jobqueue.task_done()# 创建任务队列
jobqueue = queue.Queue()# 调度多个相同间隔的任务,将任务放入队列
schedule.every(5).seconds.do(jobqueue.put, [job,"job1"])
schedule.every(5).seconds.do(jobqueue.put, [job,"job2"])
schedule.every(5).seconds.do(jobqueue.put, [job,"job3"])
schedule.every(5).seconds.do(jobqueue.put, [job,"job4"])
schedule.every(5).seconds.do(jobqueue.put, [job,"job5"])# 启动工作线程,对对任务队列进行处理
worker_thread = threading.Thread(target=worker_main)
worker_thread.start()while True:schedule.run_pending()time.sleep(1)

如果不需要队列统一调用,代码如下:

import time
import threading
import schedule
import queue
from datetime import datetime# 获取当前时间并格式化为字符串
def get_now_time():now = datetime.now()now = now.strftime("%Y-%m-%d %H:%M:%S")return now# 定义任务函数,打印当前时间和任务名称
def job(name):print(f"{get_now_time()} {name}")  def run_threaded(job_func,name):job_thread = threading.Thread(target=job_func,args=(name,))job_thread.start()schedule.every(5).seconds.do(run_threaded, job, 'job1')
schedule.every(5).seconds.do(run_threaded, job, 'job2')
schedule.every(5).seconds.do(run_threaded, job, 'job3')
schedule.every(5).seconds.do(run_threaded, job, 'job4')
schedule.every(5).seconds.do(run_threaded, job, 'job5')while True:schedule.run_pending()time.sleep(1)

异常处理

调度程序不会捕获任务执行过程中发生的异常,并将异常传递给调用函数,可能直接崩溃程序:

import schedule
import timedef bad_task():return 1 / 0schedule.every(1).minutes.do(bad_task)while True:schedule.run_pending()time.sleep(1)

如果需要防范此类异常,可以按如下方式用装饰器封装任务函数:

import schedule  
import time     
import functools # 导入函数工具库# 定义一个捕获异常的装饰器,用于包装定时任务
def catch_exceptions(cancel_on_failure=False):def catch_exceptions_decorator(job_func):@functools.wraps(job_func)  # 保留被装饰函数的元信息def wrapper(*args, **kwargs):try:return job_func(*args, **kwargs)  # 执行原函数except:import tracebackprint(traceback.format_exc())  # 打印完整的异常堆栈信息if cancel_on_failure:  # 如果设置了失败后取消任务return schedule.CancelJob  # 返回取消任务的标志return wrapperreturn catch_exceptions_decorator# 使用装饰器包装任务函数,设置失败后自动取消
@catch_exceptions(cancel_on_failure=True)
def bad_task():return 1 / 0 schedule.every(1).minutes.do(bad_task)# 主循环:持续检查并执行待处理的任务
while True:schedule.run_pending() time.sleep(1)          

日志管理

通过logging库设置名为schedule的日志记录器并设置为DEBUG级别,使其能够捕获并处理schedule库内部产生的所有日志信息:

import schedule  
import logging  # 配置基本日志设置
logging.basicConfig()
# 获取名为'schedule'的日志记录器
# 由于schedule库在内部使用相同的名称('schedule')记录自己的日志
# 因此这个记录器可以捕获并处理schedule模块产生的所有日志信息
schedule_logger = logging.getLogger('schedule')
# 设置日志级别为DEBUG,以便记录详细的调试信息
schedule_logger.setLevel(level=logging.DEBUG)def job():print("Hello, Logs")  # 打印信息到标准输出和logschedule.every().second.do(job)# 立即运行所有已安排的任务(仅执行一次)
schedule.run_all()# 清除所有已安排的任务
schedule.clear()

如果若想为任务添加可复用的日志记录功能,最简便的方法是实现一个处理日志的装饰器:

import functools
import time
import schedule# 这个装饰器可用于任何任务函数,用于记录每次任务的执行时间
def print_elapsed_time(func):@functools.wraps(func) # 让被装饰函数的名称、文档字符串等属性保持不变。def wrapper(*args, **kwargs):# 记录任务开始时间戳start_timestamp = time.time()print(f'LOG: 正在运行任务 "{func.__name__}"')# 执行实际任务result = func(*args, **kwargs)# 计算并打印任务执行耗时print(f'LOG: 任务 "{func.__name__}" 已完成,耗时 {time.time() - start_timestamp:.1f} 秒')return resultreturn wrapper# 应用装饰器,自动记录该任务的执行时间
@print_elapsed_time
def job():print('Hello, Logs')# 模拟耗时操作time.sleep(2)schedule.every().second.do(job)# 立即运行所有已注册的任务一次
schedule.run_all()

多调度程序运行

从一个调度程序里运行多少个任务都可以。不过要是调度程序规模比较大,可能需要用多个调度程序来管理。如下所示:

import time
import schedule
from datetime import datetime# 获取当前时间并格式化为字符串
def get_now_time():now = datetime.now()now = now.strftime("%Y-%m-%d %H:%M:%S")return nowdef fooJob(caller):print(f"{get_now_time()} Foo called by {caller}")def barJob(caller):print(f"{get_now_time()} Bar called by {caller}")scheduler1 = schedule.Scheduler()
scheduler1.every().hour.do(fooJob, caller="scheduler1")
scheduler1.every().hour.do(barJob, caller="scheduler1")scheduler2 = schedule.Scheduler()
scheduler2.every().second.do(fooJob, caller="scheduler2")
scheduler2.every().second.do(barJob, caller="scheduler2")# 主循环,使程序持续运行,不断检查并执行待处理的任务
while True:# 检查scheduler1中是否有待执行的任务,若有则执行scheduler1.run_pending()# 检查scheduler2中是否有待执行的任务,若有则执行scheduler2.run_pending()time.sleep(1)

2 参考

  • schedule
  • schedule-doc

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/81675.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React的合成事件(SyntheticEventt)

文章目录 前言 前言 React的合成事件(SyntheticEvent)是React为了统一不同浏览器的事件处理行为而封装的一套跨浏览器事件系统。它与原生事件的主要区别如下: 1. 事件绑定方式 • 合成事件:使用驼峰命名法绑定事件(如…

报表控件stimulsoft教程:如何在报表和仪表板中创建热图

Stimulsoft Ultimate (原Stimulsoft Reports.Ultimate)是用于创建报表和仪表板的通用工具集。该产品包括用于WinForms、ASP.NET、.NET Core、JavaScript、WPF、PHP、Java和其他环境的完整工具集。无需比较产品功能,Stimulsoft Ultimate包含了…

[免费]苍穹微信小程序外卖点餐系统修改版(跑腿点餐系统)(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好,我是java1234_小锋老师,看到一个不错的微信小程序医院预约挂号管理系统(uni-appSpringBoot后端Vue管理端),分享下哈。 项目视频演示 【免费】苍穹微信小程序外卖点餐系统修改版(跑腿点餐系统)(SpringBoot后端Vue管理端) Java毕业设计…

Dify 快速上手 MCP!Java 搭建 MCP Server 接入 Dify详细实战攻略

近期,MCP协议在AI领域热度飙升,成为众多开发者和行业人士热议的焦点。下文先介绍MCP究竟是什么?再详细讲下 Dify DeepSeek Java开发 MCP server 实战。 一、MCP的基本概念 MCP,全称为模型上下文协议(Model Context P…

力扣992做题笔记

左神做法的理论依据 我们可以通过 集合的包含关系 和 具体示例枚举 来直观理解这一推导过程。以下结合题目示例 1 进行详细说明: 示例 1 分析 输入:nums [1,2,1,2,3], k 2 目标:计算恰好包含 2 种不同整数 的子数组个数。 步骤一集合 A…

Kubernetes 运维操作手册:从 etcd 快照进行精确恢复

1 5 步实现 etcd 精确恢复 将快照恢复到本地 etcd 数据目录。使用恢复的数据启动本地 etcd 实例。使用 etcdctl 查询特定键(例如,ConfigMap)。使用 auger 解码以提取干净的 YAML。使用 kubectl 申请恢复到您的实时集群。 本指南将指导您从 et…

LeetCode Hot100刷题——合并区间

56. 合并区间 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。 示例 1: 输入:i…

《Metasploit框架核心模块解析与安全防护实践》​

目录 ​​一、框架模块化设计与安全验证价值​​ ​​1. 漏洞验证模块(Exploit Modules)​​ ​​2. 安全评估模块(Auxiliary Modules)​​ ​​3. 安全响应模块(Post-Exploitation)​​ ​​4. 载荷安全…

Cribl 中 Parser 扮演着重要的角色 + 例子

先看文档: Parser | Cribl Docs Parser The Parser Function can be used to extract fields out of events or reserialize (rewrite) events with a subset of fields. Reserialization will preserve the format of the events. For example, if an event contains comma…

程序设计实践--排序(1)

&#xff11;、插入排序&#xff08;一个数组&#xff09; #include<bits/stdc.h> using namespace std; const int N1e35; int a[N]; int n; int main(){cin>>n;for(int i1;i<n;i){cin>>a[i];}for(int i1;i<n;i){int va[i];int ji-1;while(j>1&am…

MAC电脑中右键后复制和拷贝的区别

在Mac电脑中&#xff0c;右键菜单中的“复制”和“拷贝”操作在功能上有所不同&#xff1a; 复制 功能&#xff1a;在选定的位置创建一个与原始文件相同的副本。快捷键&#xff1a;CommandD用于在当前位置快速复制文件&#xff0c;CommandC用于将内容复制到剪贴板。效果&…

新能源汽车焊接智能节气阀

在新能源汽车产业迅猛发展的浪潮中&#xff0c;制造工艺的优劣直接关系到车辆的性能、安全与市场竞争力。焊接&#xff0c;作为新能源汽车生产流程里的关键一环&#xff0c;无论是构建车身框架&#xff0c;还是连接电池模组&#xff0c;其质量的好坏都起着决定性作用。而在焊接…

Linux:面试题

1. 什么是中断和异常&#xff1f; 中断&#xff1a;由外部设备&#xff08;如键盘、网卡&#xff09;触发的异步事件&#xff0c;用于通知 CPU 有紧急事件需要处理。 异常&#xff1a;由 CPU 内部执行指令时产生的同步事件&#xff08;如除零错误、缺页异常&#xff09;&#…

linux关闭某端口暂用的进程

查看是哪个端口暂用 sudo netstat -tulpn | grep :80根据图片 显示 80端口暂用的 进程id是 3002 结束进程id为3002的进程 sudo kill -9 3002

【学习心得】Jupyter 如何在conda的base环境中其他虚拟环境内核

如果你在conda的base环境运行了jupyter lab打开了一个ipynb文本&#xff0c;此时选择的内核是base虚拟环境的Python内核&#xff0c;如果我想切换成其他conda虚拟环境来运行这个文件该怎么办&#xff1f;下面我们试着还原一下问题&#xff0c;并且解决问题。 【注】 这个问题出…

React Flow 边的基础知识与示例:从基本属性到代码实例详解

本文为《React Agent&#xff1a;从零开始构建 AI 智能体》专栏系列文章。 专栏地址&#xff1a;https://blog.csdn.net/suiyingy/category_12933485.html。项目地址&#xff1a;https://gitee.com/fgai/react-agent&#xff08;含完整代码示​例与实战源&#xff09;。完整介绍…

ZooKeeper 原理解析及优劣比较

大家好&#xff0c;这里是架构资源栈&#xff01;点击上方关注&#xff0c;添加“星标”&#xff0c;一起学习大厂前沿架构&#xff01; 引言 在分布式系统中&#xff0c;服务注册、配置管理、分布式锁、选举等场景都需要一个高可用、一致性强的协调服务。Apache ZooKeeper 凭…

模糊照片变清晰:照片高清修复 ComfyUI 使用教学

模糊照片变清晰 满心欢喜地翻出旧相册&#xff0c;想重温那些美好的回忆&#xff0c;结果照片却模糊不清&#xff0c;根本看不清当年的模样&#xff1b;又或者精心拍摄了一张超有氛围感的照片&#xff0c;结果因为手抖或者光线问题&#xff0c;变得模糊&#xff0c;无法发朋友圈…

IEEEtran中文献中的作者大于3个时,用et al.省略

latex&#xff1a; 在使用bib文件的时候&#xff0c;当参考文献超过三个作者时&#xff0c;第三个作者后加逗号并接上et al.。我使用的是IEEEtran.bst。 \begingroup \small \bibliographystyle{IEEEtran} \bibliography{newbmyref1} \endgroup1.需要将IEEEtran.bst添加到这个…

Android Studio Kotlin 中的方法添加灰色参数提示

在使用 Android Studio 时&#xff0c; 我发现使用 Java 编写方法后在调用方法时&#xff0c; 会自动显示灰色的参数。 但在 Kotlin 中没有显示&#xff0c; 于是找了各种方法最后找到了设置&#xff0c; 并且以本文章记录下来。 博主博客 https://blog.uso6.comhttps://blog.…