BDD - Python Behave log 为每个 Scenario 生成对应的 log 文件

BDD - Python Behave log 为每个 Scenario 生成对应的 log 文件

  • 引言
  • 应用 Behave 官网 Log 配置文件
    • 项目 Setup
      • Feature 文件
      • steps 文件
      • Log 配置文件
      • environment.py 文件
      • behave.ini
    • 执行结果
  • 直接应用 Python logging 模块
    • 方式 1:应用 log 配置文件
      • log 配置文件
      • environment.py
      • Steps 文件
      • 执行结果
    • 方式 2:logging 方法配置
      • environment.py
      • 执行结果
    • 方式 3:dictConfig 配置
      • environment.py
      • 执行结果
  • 总结

引言

文章《BDD - Python Behave log 日志》只是简单的介绍了一下 log 的基本配置,而且默认是输出到 Console,这对于日常自动化测试是不够全面的,不利于 Automation Triage。今天就来了解一下更友好的日志配制,为每个 Scenario 配置不同的 log 文件,极大地方便定位 Scenario 运行失败的原因。

想了解更多 Behave 相关的文章,欢迎阅读《Python BDD Behave 系列》,持续更新中。

应用 Behave 官网 Log 配置文件

首先应用一下 Behave 官网 Log with Configfile 例子,发现所有的日志都会输出到一个固定的文件中。目前 Behave 1.2.6 版本 context.config.setup_logging() 方法还不支持动态改变 config 文件中的参数值,但是可以通过改源码来实现,可参考 Add support for value substitution in logging config file

项目 Setup

Feature 文件

log_with_config_file.feature, 3 个 Scenarios

# BDD/Features/log/log_with_config_file.featureFeature: Logging Example@log_testScenario: First ScenarioGiven I have a scenario 1When I perform an actionThen I should see the result@log_testScenario Outline: Second ScenarioGiven I have a scenario <number>When I perform an actionThen I should see the resultExamples:|number||2||3|

steps 文件

简单的日志记录

# BDD/steps/log_with_config_file_steps.pyfrom behave import given, when, then
import logging
from behave.configuration import LogLevel@given("I have a scenario {number}")
def step_given_scenario(context, number):logging.info(f"This is a log from scenario {number}")@when("I perform an action")
def step_when_perform_action(context)logging.info("I perform an action")@then("I should see the result")
def step_then_see_result(context):logging.error("I did not see the result")

Log 配置文件

behave_logging.ini
配置了文件输出,也可以配置日志输出到文件和 Console,这里日志文件是固定的 BDD/logs/behave.log

 # BDD/config/behave_logging.ini[loggers]keys=root[handlers]keys=Console,File[formatters]keys=Brief[logger_root]level = DEBUG# handlers = Filehandlers = Console,File[handler_File]class=FileHandlerargs=("BDD/logs/behave.log", 'w')level=DEBUGformatter=Brief[handler_Console]class=StreamHandlerargs=(sys.stderr,)level=DEBUGformatter=Brief[formatter_Brief]format= LOG.%(levelname)-8s  %(name)-10s: %(message)sdatefmt=

environment.py 文件

通过调用 Behave 方法 context.config.setup_logging() 应用上面的 log 配置文件,

# BDD/environment.pydef before_all(context):# create log diros.makedirs("BDD/logs", exist_ok=True) context.config.setup_logging(configfile="BDD/config/behave_logging.ini")

behave.ini

Behave 默认 log_capture 是 true 的,运行成功的 Scenario 是不会输出日志的。所以将该值设置为 false,确保不管 Scenario 运行成功与否,都输出日志。stdout_capture 为 false 是允许输出 print 语句,为 true 则不会输出。

# behave.ini
[behave]
paths=BDD/Features/log/log_with_config_file.feature
tags = log_test
log_capture = false
stdout_capture = false

执行结果

因为 behave.ini 已经配置了 feature 文件 path 及 tags,所以只需在项目根目录下直接运行 behave 命令就可以了。

日志按配置格式输出到 Console,同时也输出到 behave.log 文件中。

PS C:\Automation\Test> behave
Feature: Logging Example # BDD/Features/log/log_with_config_file.feature:2@log_testScenario: First Scenario       # BDD/Features/log/log_with_config_file.feature:5Given I have a scenario 1    # BDD/steps/log_with_config_file_steps.py:7      
LOG.INFO      root      : This is a log from scenario 1When I perform an action     # BDD/steps/log_with_config_file_steps.py:14     
LOG.INFO      root      : I perform an actionThen I should see the result # BDD/steps/log_with_config_file_steps.py:22     
LOG.ERROR     root      : I did not see the result
scenario_name Second_Scenario_--_@1.1_@log_testScenario Outline: Second Scenario -- @1.1   # BDD/Features/log/log_with_config_file.feature:18Given I have a scenario 2                 # BDD/steps/log_with_config_file_steps.py:7
LOG.INFO      root      : This is a log from scenario 2When I perform an action                  # BDD/steps/log_with_config_file_steps.py:14
LOG.INFO      root      : I perform an actionThen I should see the result              # BDD/steps/log_with_config_file_steps.py:22
LOG.ERROR     root      : I did not see the result
scenario_name Second_Scenario_--_@1.2_@log_testScenario Outline: Second Scenario -- @1.2   # BDD/Features/log/log_with_config_file.feature:19Given I have a scenario 3                 # BDD/steps/log_with_config_file_steps.py:7
LOG.INFO      root      : This is a log from scenario 3When I perform an action                  # BDD/steps/log_with_config_file_steps.py:14
LOG.INFO      root      : I perform an actionThen I should see the result              # BDD/steps/log_with_config_file_steps.py:22
LOG.ERROR     root      : I did not see the result1 feature passed, 0 failed, 0 skipped
3 scenarios passed, 0 failed, 0 skipped
9 steps passed, 0 failed, 0 skipped, 0 undefined
Took 0m0.010s

在这里插入图片描述

直接应用 Python logging 模块

针对不同的 Scenario 动态创建 log 文件,输出到对应的 log 文件中,这里有三种方式实现

方式 1:应用 log 配置文件

log 配置文件

注意 args=(‘%(logfilename)s’,‘w’) 文件名可通过参数来设置的,不再是固定的。

# BDD/config/logging.ini
[loggers]
keys=root[handlers]
keys=consoleHandler,fileHandler[formatters]
keys=sampleFormatter[logger_root]
level=DEBUG
handlers=consoleHandler,fileHandler[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=sampleFormatter
args=(sys.stdout,)[handler_fileHandler]
class=FileHandler
level=DEBUG
formatter=sampleFormatter
args=('%(logfilename)s','w')[formatter_sampleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=%Y-%m-%d %H:%M:%S[log_file_template]
path={scenario_name}_{timestamp}.log

environment.py

根据 feature 名 和 Scenario 名及其位置生成 log 文件名

logging.config.fileConfig(“BDD/config/logging.ini”, defaults={‘logfilename’: log_file}) 应用 log 配置文件和动态设置 log 输出文件名
context.logger = logging.getLogger(f"{feature_name_str}_@{scenario_location_line}") 保持 log 的上下文关系

# BDD/environment.pydef before_scenario(context, scenario):# create log dirfeature_name_str = context.feature.name.replace(" ", "_")log_dir = f"BDD/logs/{feature_name_str}"os.makedirs(log_dir, exist_ok=True) # generate log file pathscenario_name = scenario.name.replace(" ", "_")current_time = datetime.datetime.now()formatted_time = current_time.strftime("%Y-%m-%d-%H-%M-%S")scenario_location_line = scenario.location.linelog_file = os.path.join(log_dir, f"{scenario_name}_{scenario_location_line}_{formatted_time}.log")# log setuplogging.config.fileConfig("BDD/config/logging.ini", defaults={'logfilename': log_file})context.logger = logging.getLogger(f"{feature_name_str}_@{scenario_location_line}")

Steps 文件

context.logger 拿到 logger 对象

# BDD/steps/log_with_config_file_steps.pyfrom behave import given, when, then
import logging
from behave.configuration import LogLevel@given("I have a scenario {number}")
def step_given_scenario(context, number):context.logger.info(f"This is a log from scenario {number}")@when("I perform an action")
def step_when_perform_action(context):context.logger.error(f"I perform an action")@then("I should see the result")
def step_then_see_result(context):context.logger.error("I should see the result")

执行结果

behave.ini 文件中的配置还跟之前一样,在项目根目录下直接运行 behave 命令即可。

log 有输出到终端:

PS C:Automation\Test> behave    
Feature: Logging Example # BDD/Features/log/log_with_config_file.feature:2@log_testScenario: First Scenario       # BDD/Features/log/log_with_config_file.feature:5Given I have a scenario 1    # BDD/steps/log_with_config_file_steps.py:7      
2024-03-09 16:00:09 - Logging_Example_@5 - INFO - This is a log from scenario 1   When I perform an action     # BDD/steps/log_with_config_file_steps.py:14     
2024-03-09 16:00:09 - Logging_Example_@5 - ERROR - I perform an actionThen I should see the result # BDD/steps/log_with_config_file_steps.py:22
2024-03-09 16:00:10 - Logging_Example_@5 - ERROR - I should see the result@log_testScenario Outline: Second Scenario -- @1.1   # BDD/Features/log/log_with_config_file.feature:18Given I have a scenario 2                 # BDD/steps/log_with_config_file_steps.py:7
2024-03-09 16:00:10 - Logging_Example_@18 - INFO - This is a log from scenario 2When I perform an action                  # BDD/steps/log_with_config_file_steps.py:14
2024-03-09 16:00:10 - Logging_Example_@18 - ERROR - I perform an actionThen I should see the result              # BDD/steps/log_with_config_file_steps.py:22
2024-03-09 16:00:10 - Logging_Example_@18 - ERROR - I should see the result@log_testScenario Outline: Second Scenario -- @1.2   # BDD/Features/log/log_with_config_file.feature:19Given I have a scenario 3                 # BDD/steps/log_with_config_file_steps.py:7
2024-03-09 16:00:10 - Logging_Example_@19 - INFO - This is a log from scenario 3When I perform an action                  # BDD/steps/log_with_config_file_steps.py:14
2024-03-09 16:00:10 - Logging_Example_@19 - ERROR - I perform an actionThen I should see the result              # BDD/steps/log_with_config_file_steps.py:22
2024-03-09 16:00:10 - Logging_Example_@19 - ERROR - I should see the result1 feature passed, 0 failed, 0 skipped
3 scenarios passed, 0 failed, 0 skipped
9 steps passed, 0 failed, 0 skipped, 0 undefined
Took 0m0.015s    

同时,feature 名的 log 目录已经创建,并每个 Scenario 都有对应的 log 文件

在这里插入图片描述

在这里插入图片描述

方式 2:logging 方法配置

在 environment.py 文件中,通过 logging 模块方法配置 log 属性, 其它文件跟方式 1 保持不变

environment.py

# BDD/environment.pydef scenario_log_setup(scenario, log_file):# set loggerlogger = logging.getLogger(scenario.name)logger.setLevel(logging.DEBUG)# add handler for loggerfile_handler = logging.FileHandler(log_file)file_handler.setLevel(logging.DEBUG)console_handler = logging.StreamHandler()console_handler.setLevel(logging.DEBUG)# set format for loggerlog_format = '%(asctime)s %(levelname)s : %(message)s'formatter = logging.Formatter(log_format)file_handler.setFormatter(formatter)console_handler.setFormatter(formatter)logger.addHandler(file_handler)logger.addHandler(console_handler)return loggerdef before_scenario(context, scenario):# create log dirfeature_name_str = context.feature.name.replace(" ", "_")log_dir = f"BDD/logs/{feature_name_str}"os.makedirs(log_dir, exist_ok=True) # generate log file pathscenario_name = scenario.name.replace(" ", "_")  current_time = datetime.datetime.now()formatted_time = current_time.strftime("%Y-%m-%d-%H-%M-%S")scenario_location_line = scenario.location.linelog_file = os.path.join(log_dir, f"{scenario_name}_{scenario_location_line}_{formatted_time}.log")# log setupcontext.logger = scenario_log_setup(scenario, log_file)

执行结果

终端输出并写入 log 文件中

PS C:\Automation\Test> behave
Feature: Logging Example # BDD/Features/log/log_with_config_file.feature:2        @log_testScenario: First Scenario       # BDD/Features/log/log_with_config_file.feature:5Given I have a scenario 1    # BDD/steps/log_with_config_file_steps.py:7      
2024-03-09 16:42:02,505 CRITICAL : This is a log from scenario 1When I perform an action     # BDD/steps/log_with_config_file_steps.py:14     
2024-03-09 16:42:02,505 ERROR : I perform an actionThen I should see the result # BDD/steps/log_with_config_file_steps.py:22     
2024-03-09 16:42:02,505 ERROR : I should see the result@log_testScenario Outline: Second Scenario -- @1.1   # BDD/Features/log/log_with_config_file.feature:18Given I have a scenario 2                 # BDD/steps/log_with_config_file_steps.py:7       
2024-03-09 16:42:02,533 CRITICAL : This is a log from scenario 2When I perform an action                  # BDD/steps/log_with_config_file_steps.py:14
2024-03-09 16:42:02,534 ERROR : I perform an actionThen I should see the result              # BDD/steps/log_with_config_file_steps.py:22
2024-03-09 16:42:02,534 ERROR : I should see the result@log_testScenario Outline: Second Scenario -- @1.2   # BDD/Features/log/log_with_config_file.feature:19Given I have a scenario 3                 # BDD/steps/log_with_config_file_steps.py:7
2024-03-09 16:42:02,541 CRITICAL : This is a log from scenario 3When I perform an action                  # BDD/steps/log_with_config_file_steps.py:14
2024-03-09 16:42:02,543 ERROR : I perform an actionThen I should see the result              # BDD/steps/log_with_config_file_steps.py:22
2024-03-09 16:42:02,545 ERROR : I should see the result1 feature passed, 0 failed, 0 skipped
3 scenarios passed, 0 failed, 0 skipped
9 steps passed, 0 failed, 0 skipped, 0 undefined
Took 0m0.018s

log 文件生成

在这里插入图片描述

在这里插入图片描述

方式 3:dictConfig 配置

在 environment.py 文件中,通过定义一个 Log Config dict 调用 logging.config.dictConfig 配置 log 属性, 其它文件跟方式 1 保持不变

environment.py

def scenario_log_setup_with_config_dict(scenario, log_file):logging_config = {'version': 1,'disable_existing_loggers': False,'formatters': {'standard': {'format': '%(asctime)s %(levelname)s : %(message)s'},},'handlers': {'file_handler': {'class': 'logging.FileHandler','filename': log_file,'formatter': 'standard',},'console_handler':{'class':'logging.StreamHandler','formatter': 'standard',}},'loggers': {'': {'handlers': ['file_handler','console_handler'],'level': 'DEBUG',},}}logging.config.dictConfig(logging_config)return logging.getLogger(scenario.name)def before_scenario(context, scenario):# create log dirfeature_name_str = context.feature.name.replace(" ", "_")log_dir = f"BDD/logs/{feature_name_str}"os.makedirs(log_dir, exist_ok=True) scenario_name = scenario.name.replace(" ", "_")# generate log file pathcurrent_time = datetime.datetime.now()formatted_time = current_time.strftime("%Y-%m-%d-%H-%M-%S")scenario_location_line = scenario.location.linelog_file = os.path.join(log_dir, f"{scenario_name}_{scenario_location_line}_{formatted_time}.log")# log setup# good 1# logging.config.fileConfig("BDD/config/logging.ini", defaults={'logfilename': log_file})# context.logger = logging.getLogger(f"{feature_name_str}_@{scenario_location_line}")# good 2# context.logger = scenario_log_setup(scenario, log_file)# good 3context.logger = scenario_log_setup_with_config_dict(scenario, log_file)

执行结果

终端输出并写入 log 文件中

PS C:\Automation\Test> behave
Feature: Logging Example # BDD/Features/log/log_with_config_file.feature:2@log_testScenario: First Scenario       # BDD/Features/log/log_with_config_file.feature:5Given I have a scenario 1    # BDD/steps/log_with_config_file_steps.py:7
2024-03-09 17:17:31,197 CRITICAL : This is a log from scenario 1When I perform an action     # BDD/steps/log_with_config_file_steps.py:14
2024-03-09 17:17:31,199 ERROR : I perform an actionThen I should see the result # BDD/steps/log_with_config_file_steps.py:22
2024-03-09 17:17:31,202 ERROR : I should see the result@log_testScenario Outline: Second Scenario -- @1.1   # BDD/Features/log/log_with_config_file.feature:18Given I have a scenario 2                 # BDD/steps/log_with_config_file_steps.py:7
2024-03-09 17:17:31,212 CRITICAL : This is a log from scenario 2When I perform an action                  # BDD/steps/log_with_config_file_steps.py:14
2024-03-09 17:17:31,212 ERROR : I perform an actionThen I should see the result              # BDD/steps/log_with_config_file_steps.py:22
2024-03-09 17:17:31,212 ERROR : I should see the result@log_testScenario Outline: Second Scenario -- @1.2   # BDD/Features/log/log_with_config_file.feature:19Given I have a scenario 3                 # BDD/steps/log_with_config_file_steps.py:7
2024-03-09 17:17:31,212 CRITICAL : This is a log from scenario 3When I perform an action                  # BDD/steps/log_with_config_file_steps.py:14
2024-03-09 17:17:31,212 ERROR : I perform an actionThen I should see the result              # BDD/steps/log_with_config_file_steps.py:22
2024-03-09 17:17:31,212 ERROR : I should see the result1 feature passed, 0 failed, 0 skipped
3 scenarios passed, 0 failed, 0 skipped
9 steps passed, 0 failed, 0 skipped, 0 undefined
Took 0m0.004s

log 文件生成
在这里插入图片描述

在这里插入图片描述

总结

上面介绍了几种 log 处理方式, 比较推荐应用 Python logging 模块采用方式 1,应用 log 配置文件,优点就是代码可读性,可维护性更好。

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

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

相关文章

ubuntu23.10安装搜狗拼音

1.添加fcitx仓库 sudo add-apt-repository ppa:fcitx-team/nightly 更新: sudo apt-get update 安装fcitx sudo apt-get install fcitx fcitx安装成功 切换输入系统为fcitx

git命令行提交——github

1. 克隆仓库至本地 git clone 右键paste&#xff08;github仓库地址&#xff09; cd 仓库路径&#xff08;进入到仓库内部准备提交文件等操作&#xff09; 2. 查看main分支 git branch&#xff08;列出本地仓库中的所有分支&#xff09; 3. 创建新分支&#xff08;可省…

Flink概述

1.什么是Flink 是一个框架和分布式处理引擎&#xff0c;用于对无界和有界数据流进行有状态计算。 官网&#xff1a;Flink 2.Flink的发展历史 Flink起源于一个叫作Stratosphere的项目&#xff0c;它是由3所地处柏林的大学和欧洲其他一些大学在2010~2014年共同进行的研究项目&a…

Yolov8模型用torch_pruning剪枝

目录 &#x1f680;&#x1f680;&#x1f680;订阅专栏&#xff0c;更新及时查看不迷路&#x1f680;&#x1f680;&#x1f680; 原理 遍历所有分组 高级剪枝器 &#x1f680;&#x1f680;&#x1f680;订阅专栏&#xff0c;更新及时查看不迷路&#x1f680;&#x1f680…

【重新定义matlab强大系列十七】Matlab深入浅出长短期记忆神经网络LSTM

&#x1f517; 运行环境&#xff1a;Matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 #### 防伪水印——左手の明天 #### &#x1f497; 大家好&#x1f917;&#x1f91…

NPP VIIRS卫星数据介绍及获取

VIIRS&#xff08;Visible infrared Imaging Radiometer&#xff09;可见光红外成像辐射仪。扫描式成像辐射仪&#xff0c;可收集陆地、大气、冰层和海洋在可见光和红外波段的辐射图像。它是高分辨率辐射仪AVHRR和地球观测系列中分辨率成像光谱仪MODIS系列的拓展和改进。VIIRS数…

java 数据结构二叉树

目录 树 树的概念 树的表示形式 二叉树 两种特殊的二叉树 二叉树的性质 二叉树的存储 二叉树的基本操作 二叉树的遍历 二叉树的基本操作 二叉树oj题 树 树是一种 非线性 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个有限结点组成一个具有层次…

vs创建asp.net core webapi发布到ISS服务器

打开服务器创建test123文件夹&#xff0c;并设置共享。 ISS配置信息&#xff1a; 邮件网站&#xff0c;添加网站 webapi asp.net core发布到ISS服务器网页无法打开解决方法 点击ISS Express测试&#xff0c;可以成功打开网页。 点击生成&#xff0c;发布到服务器 找到服务器IP…

OJ_复数集合

题干 C实现 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <queue> #include <string> using namespace std;struct Complex {int re;int im;//构造函数Complex(int _re, int _im) {//注意参数名字必须不同re _re;im _im;} };//结构体不支…

新闻文章分类项目

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; 新闻文章分类模型比较项目报告 项目介绍 背景 新闻文章自动分类是自然语言处理和文本挖掘领域的一个重要任务。正确分类新闻文章不仅能帮助用…

日期问题---算法精讲

前言 今天讲讲日期问题&#xff0c;所谓日期问题&#xff0c;在蓝桥杯中出现众多&#xff0c;但是解法比较固定。 一般有判断日期合法性&#xff0c;判断是否闰年&#xff0c;判断日期的特殊形式&#xff08;回文或abababab型等&#xff09; 目录 例题 题2 题三 总结 …

问题:前端获取long型数值精度丢失,后面几位都为0

文章目录 问题分析解决 问题 通过接口获取到的数据和 Postman 获取到的数据不一样&#xff0c;仔细看 data 的第17位之后 分析 该字段类型是long类型问题&#xff1a;前端接收到数据后&#xff0c;发现精度丢失&#xff0c;当返回的结果超过17位的时候&#xff0c;后面的全…

[java入门到精通] 11 泛型,数据结构,List,Set

今日目标 泛型使用 数据结构 List Set 1 泛型 1.1 泛型的介绍 泛型是一种类型参数&#xff0c;专门用来保存类型用的 最早接触泛型是在ArrayList&#xff0c;这个E就是所谓的泛型了。使用ArrayList时&#xff0c;只要给E指定某一个类型&#xff0c;里面所有用到泛型的地…

【C++】函数重载

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:C ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;函数重载的定义 &#x1f4cc;函数重载的三种类型 &#x1f38f;参数个数不同 &#x1f38f;参数类型不同 &#x1f38f;参数类型顺序不同 &#x1f4cc;重载…

用C语言执行SQLite3的gcc编译细节

错误信息&#xff1a; /tmp/cc3joSwp.o: In function main: execSqlite.c:(.text0x100): undefined reference to sqlite3_open execSqlite.c:(.text0x16c): undefined reference to sqlite3_exec execSqlite.c:(.text0x174): undefined reference to sqlite3_close execSqlit…

❤ Vue3项目搭建系统篇(二)

❤ Vue3项目搭建系统篇&#xff08;二&#xff09; 1、安装和配置 Element Plus&#xff08;完整导入&#xff09; yarn add element-plus --savemain.ts中引入&#xff1a; // 引入组件 import ElementPlus from element-plus import element-plus/dist/index.css const ap…

STL之deque容器代码详解

1 基础概念 功能&#xff1a; 双端数组&#xff0c;可以对头端进行插入删除操作。 deque与vector区别&#xff1a; vector对于头部的插入删除效率低&#xff0c;数据量越大&#xff0c;效率越低。 deque相对而言&#xff0c;对头部的插入删除速度回比vector快。 vector访问…

jpg 转 ico 强大的图片处理工具 imageMagick

点击下载 windows, mac os, linux版本 GitHub - ImageMagick/ImageMagick: &#x1f9d9;‍♂️ ImageMagick 7 1. windows程序 链接&#xff1a;https://pan.baidu.com/s/1wZLqpcytpCVAl52pIrBBEw 提取码&#xff1a;hbfy 一直点击下一步安装 2. 然后 winr键 打开cmd 然…

SSD的原理

简介 SSD&#xff08;Solid State Drive&#xff09;是一种使用闪存存储芯片&#xff08;NAND Flash&#xff09;的存储设备。与传统的机械硬盘不同&#xff0c;SSD没有移动部件&#xff0c;因此具有更快的读写速度和更低的能耗。 架构 NAND Flash是一种非易失性存储器&…

nodejs web服务器 -- 搭建开发环境

一、配置目录结构 1、使用npm生成package.json&#xff0c;我创建了一个nodejs_network 文件夹&#xff0c;cd到这个文件夹下&#xff0c;执行&#xff1a; npm init -y 其中-y的含义是yes的意思&#xff0c;在init的时候省去了敲回车的步骤&#xff0c;如此就生成了默认的pac…