python - 在linux上编译py文件为【.so】文件部署项目运行
python - 在linux上编译py文件为【.so】文件,可通过主文件直接执行
一. 前言
在Python中,通常不直接将Python代码编译为.so(共享对象)文件来执行,因为.so文件是编译后的二进制代码,通常用于C或C++等语言,并且它们被设计为可以被Python(通过C API)或其他语言(如C或C++)动态加载和执行。
二.打包编译项目
准备工作
一般linux上都会有GCC编译器,如若没有请先安装
1.安装Cython
pip install cython
2.将以下的脚本放在deploy目录下,项目所有文件放在project下面即可

1.编译为.c文件的代码
创建一个setup_cmd.py文件
import logging
import osfrom setuptools import setup
from Cython.Build import cythonize# ============================== 配置日志 ===============================
# 定义日志文件的名称
log_filename = 'setup_cmd.log'# 创建一个日志记录器
logger = logging.getLogger()
logger.setLevel(logging.INFO) # 设置日志级别为 INFO# 创建一个文件处理器,并设置级别为 INFO
file_handler = logging.FileHandler(log_filename, encoding='utf-8') # 指定编码为 utf-8
file_handler.setLevel(logging.INFO)# 创建一个流处理器(控制台输出),并设置级别为 INFO
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)# 创建日志格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
stream_handler.setFormatter(formatter)# 将处理器添加到日志记录器
logger.addHandler(file_handler)
logger.addHandler(stream_handler)# ============================== 配置日志 ===============================
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 设置 BASE_DIR
logger.info(f"BASE_DIR -> {BASE_DIR}\n")# 获取需要编译的文件列表
def get_py_files(directory, exclude_folders, exclude_file_list):py_files = []for root, dirs, files in os.walk(directory):for d in dirs:if d in exclude_folders:dirs.remove(d)for file in files:if file in exclude_file_list:logger.info(f"不需要编译文件:[{file}] 在 {exclude_file_list} 中!")continueif file.endswith('.py') and '-' not in file:py_files.append(os.path.join(root, file))logger.info(f'py_files -> {py_files}')logger.info(f'py_files count -> {len(py_files)}')return py_filesexclude_folders = ['tests', '.git', '.idea', '__pycache__', 'a-deploy', 'deploy']
exclude_file_list = ['app.py']# 1.编译打包
file_list = get_py_files(BASE_DIR, exclude_folders, exclude_file_list)
# 单个文件编译或多个文件
# file_list = ['/opt/pkg/project/dev/service/sessionService/service_impl/nw_session_history.py']
setup(ext_modules=cythonize(file_list, language_level=3), # 使用 Python 3 的语言级别
)
1.在linux环境下可直接执行文件
python3 setup_cmd.py
2.windows上直接使用命令执行
python3 setup_cmd.py build_ext --inplace
2.将.c文件转化为.so文件
创建setup_compile_file.py文件
主要是将以下命令拆解执行
gcc -pthread -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/usr/local/include/python3.11 -c /opt/pkg/project/dev/base/utils/handle_tasks.c -o build/temp.linux-x86_64-cpython-311/opt/pkg/project/dev/base/utils/handle_tasks.o
gcc -pthread -shared build/temp.linux-x86_64-cpython-311/opt/pkg/project/dev/base/utils/handle_tasks.o -o build/lib.linux-x86_64-cpython-311/handle_tasks.cpython-311-x86_64-linux-gnu.so
代码如下,参考函数:compile_c_files
# -*- coding: utf-8 -*-
import logging
import os
import shutil
import subprocessfrom setuptools import setup
from Cython.Build import cythonizeimport osfrom concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETEDexecutor = ThreadPoolExecutor(max_workers=50)# ============================== 配置日志 ===============================
# 定义日志文件的名称
log_filename = 'setup_compile_file.log'# 创建一个日志记录器
logger = logging.getLogger()
logger.setLevel(logging.INFO) # 设置日志级别为 INFO# 创建一个文件处理器,并设置级别为 INFO
file_handler = logging.FileHandler(log_filename, encoding='utf-8') # 指定编码为 utf-8
file_handler.setLevel(logging.INFO)# 创建一个流处理器(控制台输出),并设置级别为 INFO
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)# 创建日志格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
stream_handler.setFormatter(formatter)# 将处理器添加到日志记录器
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
# ============================== 配置日志 ===============================# BASE_DIR = os.getcwd()
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 设置 BASE_DIR
logger.info(f"BASE_DIR -> {BASE_DIR}\n")executor = ThreadPoolExecutor(max_workers=10) # 根据需要调整线程数# 获取需要编译的文件列表
def get_py_files(directory, exclude_folders, exclude_file_list):py_files = []for root, dirs, files in os.walk(directory):for d in dirs:if d in exclude_folders:dirs.remove(d)for file in files:if file in exclude_file_list:logger.info(f"不需要编译文件:[{file}] 在 {exclude_file_list} 中!")continueif file.endswith('.py') and '-' not in file:py_files.append(os.path.join(root, file))logger.info(f'py_files -> {py_files}')logger.info(f'py_files count -> {len(py_files)}')return py_files# 编译扩展模块
def compile_pkg(file_list):setup(ext_modules=cythonize(file_list, language_level=3), # 使用 Python 3 的语言级别)subprocess.run(['python3', 'setup_compile_file.py', 'build_ext', '--inplace'])#
def copy_compiled_files(source_dir, target_dir, exclude_folders, exclude_file_list):""" 拷贝处理编译好的文件 """if os.path.exists(target_dir):shutil.rmtree(target_dir)logger.info(f"已删除旧的目标文件夹: {target_dir}")os.makedirs(target_dir)logger.info(f"已创建新的目标文件夹: {target_dir}")ans = 0# 遍历源文件夹 for root, dirs, files in os.walk(source_dir):# 过滤掉要排除的文件夹 dirs[:] = [d for d in dirs if d not in exclude_folders]# 遍历当前文件夹中的文件for file in files:try:if file in exclude_file_list:logger.info(f"不拷贝文件:[{file}] 在 exclude_file_list:{exclude_file_list} 中!")continue# 构造源和目标文件路径src_file = os.path.join(root, file)rel_path = os.path.relpath(root, source_dir)dst_file = os.path.join(target_dir, rel_path, file)# 确保目标文件夹存在os.makedirs(os.path.dirname(dst_file), exist_ok=True)# 拷贝文件shutil.copy2(src_file, dst_file)ans += 1logger.info(f'文件拷贝成功[src_file]:{src_file} -> [dst_file]:{dst_file}')except Exception as e:logger.info(f'文件拷贝异常:file:{file} -> error:{e}')logger.info(f"已成功拷贝编译文件,数量:{ans}")def delete_specific_files(folder, extensions, exclude_file_list):"""在指定文件夹中删除所有以extensions中指定的扩展名结尾的文件。:param folder: 文件夹路径:param extensions: 要删除的文件扩展名列表"""# 遍历文件夹logger.info(f"")ans = 0for root, dirs, files in os.walk(folder):for file in files:if file in exclude_file_list:logger.info(f"不删除文件:[{file}] 在 exclude_file_list:{exclude_file_list} 中!")continueif file.endswith(tuple(extensions)):os.remove(os.path.join(root, file))logger.info(f"已删除含有 {extensions} 的文件: {os.path.join(root, file)}")ans += 1logger.info(f"已删除以{extensions}结尾的文件数量:{ans}")def compile_c_files(target_dir, extensions, exclude_folders, exclude_file_list):"""编译文件(linux下的命令)gcc -pthread -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/usr/local/include/python3.11 -c /opt/pkg/project/dev/base/utils/handle_tasks.c -o build/temp.linux-x86_64-cpython-311/opt/pkg/project/dev/base/utils/handle_tasks.ogcc -pthread -shared build/temp.linux-x86_64-cpython-311/opt/pkg/project/dev/base/utils/handle_tasks.o -o build/lib.linux-x86_64-cpython-311/handle_tasks.cpython-311-x86_64-linux-gnu.so"""# 遍历文件夹ans = 0futures = []for root, dirs, files in os.walk(target_dir):for file in files:if file in exclude_file_list:logger.info(f"文件:{file} 在 exclude_file_list:{exclude_file_list} 中,不需要编译!")continueif file.endswith(tuple(extensions)):c_path = os.path.join(root, file)file_name = file.split('.')[0]# o_path = root + '/' + file_name + '.o'o_path = os.path.join(root, file_name + '.o')# so_path = root + '/' + file_name + '.cpython-311-x86_64-linux-gnu.so'so_path = os.path.join(root, file_name + '.cpython-311-x86_64-linux-gnu.so')logger.info(f'c_path - > {c_path}')logger.info(f'o_path - > {o_path}')logger.info(f'so_path - > {so_path}')future = executor.submit(compile_file_to_so, c_path, o_path, so_path)futures.append(future)ans += 1logger.info(f'complied count -----> {ans}')# 等待所有任务完成wait(futures, return_when=ALL_COMPLETED)logger.info(f"已编译文件数量:{ans}")def compile_file_to_so(c_path, o_path, so_path):os.system(f"gcc -pthread -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/usr/local/include/python3.11 -c {c_path} -o {o_path}")os.system(f"gcc -pthread -shared {o_path} -o {so_path}")logger.info(f'File success compiled to - > {so_path}')def main():exclude_folders = ['tests', '.git', '.idea', '__pycache__', 'a-deploy', 'deploy']exclude_file_list = ['app.py', 'app.c']logger.info(f'项目编译打包开始,源码文件路劲:{BASE_DIR}\n')# try:# # 单个文件编译或多个文件# # file_list = ['/opt/pkg/project/dev/service/sessionService/service_impl/nw_session_history.py']## # 1.编译打包# file_list = get_py_files(BASE_DIR, exclude_folders, exclude_file_list)# compile_pkg(file_list)# ...# except Exception as e:# logger.info(f'Exception:{e}')source_dir = BASE_DIRtarget_dir = os.path.join(BASE_DIR, 'deploy', 'dist')# 清除['.c']文件extensions = ['.c']logger.info(f'开始清除项目中含有{extensions}结尾的文件 [target_dir]:{target_dir}\n')delete_specific_files(target_dir, extensions, exclude_file_list)logger.info(f'结束清除项目中含有{extensions}结尾的文件 [target_dir]:{target_dir}\n')# 2.复制编译好的文件logger.info(f'复制拷贝项目开始 [source_dir]:{source_dir} -> [target_dir]:{target_dir}\n')copy_compiled_files(source_dir, target_dir, exclude_folders, ['app.c'])logger.info(f'复制拷贝项目结束 [source_dir]:{source_dir} -> [target_dir]:{target_dir}\n')# # 3.删除py文件# extensions = ['.py']# logger.info(f'开始删除拷贝项目中含有{extensions}结尾的文件 [target_dir]:{target_dir}\n')# delete_specific_files(target_dir, extensions, exclude_file_list)# logger.info(f'结束删除拷贝项目中含有{extensions}结尾的文件 [target_dir]:{target_dir}\n')# 4.编译项目['.c']文件 -> ['.so', 'pyd']compile_extensions = ['.c']logger.info(f"开始编译项目{compile_extensions}文件 -> ['.so', 'pyd']\n")compile_c_files(target_dir, compile_extensions, exclude_folders, exclude_file_list)logger.info(f"结束编译项目{compile_extensions}文件 -> ['.so', 'pyd']\n")logger.info(f'项目编译处理完成,源码文件路劲:{source_dir}\n')logger.info(f'项目编译处理完成,编译打包文件路劲:{target_dir}\n')if __name__ == '__main__':main()
3.清理编译后的项目文件
创建clean_compile_file.py文件
# -*- coding: utf-8 -*-
import loggingimport osfrom concurrent.futures import ThreadPoolExecutorexecutor = ThreadPoolExecutor(max_workers=50)# ============================== 配置日志 ===============================
# 定义日志文件的名称
log_filename = 'setup_compile_file.log'# 创建一个日志记录器
logger = logging.getLogger()
logger.setLevel(logging.INFO) # 设置日志级别为 INFO# 创建一个文件处理器,并设置级别为 INFO
file_handler = logging.FileHandler(log_filename, encoding='utf-8') # 指定编码为 utf-8
file_handler.setLevel(logging.INFO)# 创建一个流处理器(控制台输出),并设置级别为 INFO
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)# 创建日志格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
stream_handler.setFormatter(formatter)# 将处理器添加到日志记录器
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
# ============================== 配置日志 ===============================# BASE_DIR = os.getcwd()
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 设置 BASE_DIR
logger.info(f"BASE_DIR -> {BASE_DIR}\n")def delete_specific_files(folder, extensions, exclude_file_list):"""在指定文件夹中删除所有以extensions中指定的扩展名结尾的文件。:param folder: 文件夹路径:param extensions: 要删除的文件扩展名列表"""# 遍历文件夹logger.info(f"")ans = 0for root, dirs, files in os.walk(folder):for file in files:if file in exclude_file_list:logger.info(f"不删除文件:[{file}] 在 exclude_file_list:{exclude_file_list} 中!")continueif file.endswith(tuple(extensions)):os.remove(os.path.join(root, file))logger.info(f"已删除含有 {extensions} 的文件: {os.path.join(root, file)}")ans += 1logger.info(f"已删除以{extensions}结尾的文件数量:{ans}")def main():exclude_folders = ['tests', '.git', '.idea', '__pycache__', 'a-deploy', 'deploy']exclude_file_list = ['app.py', 'app.c']logger.info(f'========= 项目编译文件清理完成开始 ========\n')target_dir = os.path.join(BASE_DIR, 'deploy', 'dist')# 删除py文件extensions = ['.py', '.o', '.pyd', '.c']logger.info(f'开始删除拷贝项目中含有{extensions}结尾的文件 [target_dir]:{target_dir}\n')delete_specific_files(target_dir, extensions, exclude_file_list)logger.info(f'结束删除拷贝项目中含有{extensions}结尾的文件 [target_dir]:{target_dir}\n')# # 删除源码下的['.so', 'pyd', '.c']文件# src_extensions = ['.so', 'pyd', '.c']# logger.info(f"开始删除源码下的{src_extensions}文件\n")# delete_specific_files(source_dir, src_extensions)# logger.info(f"结束删除源码下的{src_extensions}文件\n")logger.info(f'========= 项目编译文件清理完成!=========\n')if __name__ == '__main__':main()
其他操作
清理源代码下的.c文件(可选)
clean_code_c_file.py
# -*- coding: utf-8 -*-
import loggingimport osfrom concurrent.futures import ThreadPoolExecutorexecutor = ThreadPoolExecutor(max_workers=50)# ============================== 配置日志 ===============================
# 定义日志文件的名称
log_filename = 'setup_compile_file.log'# 创建一个日志记录器
logger = logging.getLogger()
logger.setLevel(logging.INFO) # 设置日志级别为 INFO# 创建一个文件处理器,并设置级别为 INFO
file_handler = logging.FileHandler(log_filename, encoding='utf-8') # 指定编码为 utf-8
file_handler.setLevel(logging.INFO)# 创建一个流处理器(控制台输出),并设置级别为 INFO
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)# 创建日志格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
stream_handler.setFormatter(formatter)# 将处理器添加到日志记录器
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
# ============================== 配置日志 ===============================# BASE_DIR = os.getcwd()
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 设置 BASE_DIR
logger.info(f"BASE_DIR -> {BASE_DIR}\n")def delete_specific_files(folder, extensions, exclude_file_list):"""在指定文件夹中删除所有以extensions中指定的扩展名结尾的文件。:param folder: 文件夹路径:param extensions: 要删除的文件扩展名列表"""# 遍历文件夹logger.info(f"")ans = 0for root, dirs, files in os.walk(folder):for file in files:if file in exclude_file_list:logger.info(f"不删除文件:[{file}] 在 exclude_file_list:{exclude_file_list} 中!")continueif file.endswith(tuple(extensions)):os.remove(os.path.join(root, file))logger.info(f"已删除含有 {extensions} 的文件: {os.path.join(root, file)}")ans += 1logger.info(f"已删除以{extensions}结尾的文件数量:{ans}")def main():exclude_folders = ['tests', '.git', '.idea', '__pycache__', 'a-deploy', 'deploy']exclude_file_list = ['app.py', 'app.c']logger.info(f'========= 项目编译文件清理完成开始 ========\n')source_dir = BASE_DIR# 删除源码下的['.so', 'pyd', '.c']文件src_extensions = ['.c']logger.info(f"开始删除源码下的{src_extensions}文件\n")delete_specific_files(source_dir, src_extensions, exclude_file_list)logger.info(f"结束删除源码下的{src_extensions}文件\n")logger.info(f'========= 项目源码文件清理完成!=========\n')if __name__ == '__main__':main()
shell脚本
start_setup.sh
#!/bin/bashecho "开始执行 setup_cmd.py ..."
python3 setup_cmd.py
echo "setup_cmd.py 执行完成!"echo "开始执行 setup_compile_file.py ..."
python3 setup_compile_file.py
if [ $? -eq 0 ]; thenecho "setup_compile_file.py 中的所有任务执行成功完成!"
elseecho "setup_compile_file.py 执行失败或任务未完成,请检查错误。"exit 1
fi# 等待 setup_compile_file.py 中的所有线程完成后,执行 clean_compile_file.py
echo "开始执行 clean_compile_file.py ..."
python3 clean_compile_file.py
if [ $? -eq 0 ]; thenecho "clean_compile_file.py 执行成功!"
elseecho "clean_compile_file.py 执行失败,请检查错误。"exit 1
fiecho "所有脚本执行完毕。"
Cython只是帮助我们将Python代码(或Python风格的代码)转换成了C代码,然后编译成了二进制形式。这个过程并不是传统意义上的“编译Python代码为机器码执行”,而是利用了C的编译效率和Python的易用性之间的平衡。
本文介绍到此结束,希望对你有所帮助!
相关文章:
python - 在linux上编译py文件为【.so】文件部署项目运行
python - 在linux上编译py文件为【.so】文件,可通过主文件直接执行 一. 前言 在Python中,通常不直接将Python代码编译为.so(共享对象)文件来执行,因为.so文件是编译后的二进制代码,通常用于C或C等语言&am…...
SQL_having_pandas_filter
HAVING子句在SQL中用于对分组后的结果进行过滤,它通常与GROUP BY子句一起使用。HAVING子句允许你指定条件来过滤聚合函数的结果,而WHERE子句则用于在分组之前过滤原始数据。 基本语法 SELECT column_name, aggregate_function(column_name) FROM table…...
从软件架构设计角度理解Kafka
网上对于消息中间件的介绍文章比较多,这里我们不再赘述,我们换个思路来理解消息中间件,从软件开发架构的角度来看下消息中间件是如何诞生和演进的。 一、概述 上图中P代表 Provider,C代表Consumer,下同。P和C是一个典型…...
什么是中断?
1.什么是中断 2.中断的重要性 3.中断的上下半部 4.中断处理流程 中断的原则 5.ARM处理器程序运行过程 6.程序被被中断时,怎么保护现场 1.什么是中断 中断是指在 CPU 正常运行期间, 由外部或内部事件引起的一种机制。 当中断发生时,…...
后端(实例)08
设计一个前端在数据库调取数据的表格,并完成基础点击增删改查的功能: 1.首先写一个前端样式(空壳) <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>Insert title here&l…...
【stm32】TIM定时器输出比较-PWM驱动LED呼吸灯/舵机/直流电机
TIM定时器输出比较 一、输出比较简介1、OC(Output Compare)输出比较2、PWM简介3、输出比较通道(高级)4、输出比较通道(通用)5、输出比较模式6、PWM基本结构配置步骤:程序代码:PWM驱动LED呼吸灯 7、参数计算8、舵机简介程序代码&am…...
如何使用ssm实现线上旅游体验系统+vue
TOC ssm691线上旅游体验系统vue 绪论 课题背景 身处网络时代,随着网络系统体系发展的不断成熟和完善,人们的生活也随之发生了很大的变化。目前,人们在追求较高物质生活的同时,也在想着如何使自身的精神内涵得到提升࿰…...
探索JMeterTools:一个Python驱动的JMeter脚本生成器
JMeterTools 简介 JMeterTools 是一个由 Python 编写的开源项目,旨在帮助测试人员快速生成 JMeter 测试脚本。通过简单的 Python API,用户可以方便地定义测试计划、线程组、HTTP 请求等,可以结合接口自动化测试项目,将接口自动化…...
【React】组件通信
1. 组件通信 组件间的数据传递 1.1 父传子 步骤: 父组件传递数据——在子组件标签上绑定属性子组件接收数据——子组件通过props参数接收数据 function Son(props) {return <div>{props.value}</div> }function App() {const value 父组件传给子…...
C++核心编程和桌面应用开发 第七天(运算符重载 智能指针)
目录 1.数组类 2.运算符重载 2.1加号运算符 2.1.1成员函数实现 2.1.2全局函数实现 2.1.3加号重载 2.2左移运算符 2.3递增运算符 2.4指针运算符 2.5赋值运算符 1.数组类 //默认构造函数 MyArray::MyArray() {m_Size 0;m_Capacity 100;pAddress new int[m_Capacity]…...
echarts地图的简单使用
echarts地图的简单使用 文章说明核心源码效果展示源码下载 文章说明 主要介绍echarts地图组件的简单使用,记录为文章,供后续查阅使用 目前只是简单的示例,然后还存在着一些小bug,主要是首个Legend的点击会导致颜色全部不展示的问题…...
Qt 项目优化实践方向
目录 1. 使用智能指针2. 避免在全局或静态作用域中使用裸指针3. 利用Qt的对象树进行资源管理4. 延迟加载和按需加载资源5. 合理使用Qt的资源文件(qrc)6. 监控和调试内存使用7. 优化数据结构8. 减少不必要的资源复制9. 使用缓存机制10. 遵循RAII原则 以下…...
常见的15个:自然语言处理(NLP)实战项目
自然语言处理(NLP)实战项目涵盖了从基础到高级的多个领域,以下是一些常见的NLP实战项目,每个项目都附带了简要的描述和可能用到的技术栈: 1. 文本分类(Text Classification) 描述: 将文本数据…...
CKKS同态加密通用函数近似方法和openFHE实现
摘要 同态加密可以直接在密文上进行运算,尤其是CKKS,可以直接在实数的密文上进行运算。服务器可以利用强大的计算能力,在不泄露用户隐私的情况下,为用户提供便捷的外包运算服务。然而,CKKS只能进行算术运算࿰…...
Webpack 5的新特性:Asset Modules与Dynamic Import
文章目录 Asset ModulesAsset Modules 类型配置示例分析 Dynamic Import动态导入语法配置示例分析 实际案例分析Asset Modules 实际案例Dynamic Import 实际案例 性能优化Asset Modules 性能优化Dynamic Import 性能优化 详细代码分析Asset Modules 代码分析Dynamic Import 代码…...
解释python requests包的timeout
解释python requests包的timeout 哈哈哈。。。。垃圾python又来了 1 问题 你能看懂下面两个timeout的含义就不用看下面的内容了。 requests.get(http://example.com, timeout(2, 5)) requests.get(http://127.0.0.1:5000/api,timeout1)官网解释!!&am…...
蒙语学习快速方法,速记蒙语单词怎么学习更高效!
要高效学习蒙古语和速记单词,首先要掌握基础知识,如字母表和发音规则。接着,专注于学习日常用语和基础词汇,并运用记忆技巧如联想、发音和构词法来帮助记忆。利用专门的学习软件,如“蒙语学习通”,可以提供…...
Vue3组件通信13种方法
在 Vue3 中,组件之间的通信是构建应用程序的关键 1. 父组件向子组件传递数据 (Props)「父组件:」「子组件:」 2. 子组件向父组件传递数据 (Emit)「父组件:」「子组件:」 3. 兄弟组件通信 (Mitt)「发送事件的组件:」「接收事件的组件:」 4. 透传 Attributes ($attrs)「父组件:」…...
Servlet入门:服务端小程序的初试(自己学习整理的资料)
目录 一.前言 二.建立基础结构编辑 三.具体步骤 找到Tomcat文件并打开Tomcat。 在webapps中创建一个自己的文件夹。 在classes中新建一个Java文件。 在lib中导入需要的jar文件包。 配置环境变量 在Java文件的目录下打开cmd并输入 javac -d . HelloServlet.java进行…...
代码随想录算法训练营第三七天| 动态规划:完全背包理论基础 518.零钱兑换II 377. 组合总和 Ⅳ 322. 零钱兑换
今日任务 动态规划:完全背包理论基础 518.零钱兑换II 377. 组合总和 Ⅳ 322. 零钱兑换 518.零钱兑换II 题目链接: . - 力扣(LeetCode) class Solution {public int change(int amount, int[] coins) {int[] dp new int[amount …...
Ubuntu 18.04.6 从零到一:新手避坑与高效配置实战指南
1. 为什么选择Ubuntu 18.04.6? Ubuntu 18.04.6是长期支持版本(LTS)的最终更新,特别适合需要稳定系统的用户。相比最新版本,它的软件生态更成熟,社区支持更完善。我实测发现,这个版本对老硬件兼容…...
如何用VMware Unlocker突破虚拟化限制实现macOS跨平台运行
如何用VMware Unlocker突破虚拟化限制实现macOS跨平台运行 【免费下载链接】unlocker VMware Workstation macOS 项目地址: https://gitcode.com/gh_mirrors/unloc/unlocker 你是否曾经面临这样的困境:作为Windows或Linux开发者,需要在macOS环境…...
【MYSQL】在Centos7和ubuntu22.04环境下安装
一.MYSQL在Centos7下的安装注意:安装与卸载中,⽤⼾全部切换成为root初期练习,mysql不进⾏⽤⼾管理,全部使⽤root进⾏1.卸载内置环境1-1卸载不要的环境[rootVM-0-3-centos ~]$ ps ajx |grep mariadb # 先检查是否有mariadb存在 131…...
NotebookLM文献精读陷阱警示:化学人必避的5类幻觉引用、2种结构误识别及实时校验方案
更多请点击: https://kaifayun.com 第一章:NotebookLM文献精读陷阱警示:化学人必避的5类幻觉引用、2种结构误识别及实时校验方案 NotebookLM 作为基于语义理解的AI文献助手,在化学领域高频出现“看似合理、实则失真”的推理错误。…...
如何快速掌握高效窗口管理:免费开源工具完整指南
如何快速掌握高效窗口管理:免费开源工具完整指南 【免费下载链接】AltSnap Maintained continuation of Stefan Sundins AltDrag 项目地址: https://gitcode.com/gh_mirrors/al/AltSnap 你是否曾经在Windows系统中为繁琐的窗口操作而烦恼?每次想要…...
3步搞定Linux启动盘:Deepin Boot Maker完全使用指南
3步搞定Linux启动盘:Deepin Boot Maker完全使用指南 【免费下载链接】deepin-boot-maker 项目地址: https://gitcode.com/gh_mirrors/de/deepin-boot-maker 在Linux系统安装和维护过程中,启动盘制作是一个看似简单却充满挑战的环节。传统命令行工…...
别再死记硬背了!用MATLAB手把手教你画根轨迹图(附代码与避坑指南)
MATLAB实战:从零绘制根轨迹图的完整指南与避坑技巧 在控制系统的设计与分析中,根轨迹图是理解系统动态特性的重要工具。传统教学中,学生往往被要求死记硬背绘制规则,却难以理解其实际应用价值。本文将彻底改变这一现状——通过MAT…...
告别黑盒:5分钟为你的自定义CNN模型集成Grad-CAM可视化(附常见错误排查)
告别黑盒:5分钟为你的自定义CNN模型集成Grad-CAM可视化(附常见错误排查) 在深度学习项目中,我们常常陷入一个尴尬境地:模型准确率很高,但完全不知道它究竟"看"了图像的哪些部分做出决策。这种黑盒…...
Godot游戏集成Discord状态:RPC插件原理与实战指南
1. 项目概述:在Godot引擎中点亮你的Discord状态 如果你是一名独立游戏开发者,或者正在用Godot引擎捣鼓一些有趣的个人项目,你可能会想让你的朋友或社区成员知道你现在正在“玩”什么。不是通过截图发到社交媒体,而是更实时、更优…...
SVG与CSS变量驱动的自动化品牌视觉生成技术实践
1. 项目概述:一分钟品牌塑造的实践宝库在品牌营销和创意设计领域,一个常见的痛点是如何快速、高效地生成高质量的视觉品牌资产。无论是初创公司需要一个临时的Logo,还是内容创作者想为新的系列视频设计一个统一的片头,传统的品牌设…...
