WebApi+Python PyQ5实现大文件下载,Ui增加进度条和下载速率+已验证uos和Windows环境

news2025/5/25 2:20:19

Web Api接品代码:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Concurrent;
using System.Net;

namespace LargeFileHandling.Controllers
{
    [ApiController]
    [Route("[controller]")]

    public class TestProgramFileManagerController : Controller
    {
        private readonly string _testProgramPath;

        // 用于存储文件块的信息
        private static ConcurrentDictionary<string, int> fileChunkTracker = new ConcurrentDictionary<string, int>();

        public TestProgramFileManagerController(FileStorageSettings fileStorageSettings)
        {
            _testProgramPath = fileStorageSettings.TestProgramPath;

            //确保上传文件夹存在
            if (!Directory.Exists(_testProgramPath))
            {
                Directory.CreateDirectory(_testProgramPath);//如果不存在则创建
            }
        }

        //上传测试日志
        [HttpPost("uploadTestProgram")]
        /*
         testProgramFile:测试程式文件
         ProgramDriectory:程式存放目录
         */
        public async Task<IActionResult> UploadTestProgram(IFormFile testProgramFile, string programDriectory)
        {
            try
            {
                //判断产品文件夹是否存在
                if (!Directory.Exists($@"{_testProgramPath}\{programDriectory}"))
                {
                    Directory.CreateDirectory($@"{_testProgramPath}\{programDriectory}");//如果不存在则创建
                }

                if (testProgramFile == null || testProgramFile.Length == 0)
                {
                    return BadRequest(new { code = 400, message = "Upload failed. No file provided.", data = new { } });
                }

                var filename = Path.GetFileName(testProgramFile.FileName);
                var filePath = Path.Combine($@"{_testProgramPath}\{programDriectory}", filename);

                await using (var stream = System.IO.File.Create(filePath))
                {
                    await testProgramFile.CopyToAsync(stream);
                }

                return Ok(new { code = 200, message = "test log file uploaded successfully.", data = new { filePath } });
            }
            catch (Exception ex)
            {
                // 增加更详细的错误日志
                Console.WriteLine($"Error: {ex.GetType().FullName}: {ex.Message}");
                Console.WriteLine($"Stack Trace: {ex.StackTrace}");

                // 记录到日志文件或其他监控工具(根据您的日志配置)
                // Logger.LogError(ex, "Error listing files");

                return StatusCode(500, new { code = 500, message = "UploadTestProgram Error.", details = ex.Message });
            }
        }

        // Check if file exists and return JSON response
        /*
         * 查找测试程式文件是否存在
         testProgramFile:测试程式文件
         programDriectory:程式目录
         */
        [HttpGet("exists")]
        public IActionResult CheckProgramFileExists(string testProgramFile, string programDriectory)
        {
            var filePath = Path.Combine($@"{_testProgramPath}\{programDriectory}", testProgramFile);
            if (System.IO.File.Exists(filePath))
            {
                return Ok(new { code = 200, message = "File exists.", data = new { filePath } });
            }
            else
            {
                return NotFound(new { code = 404, message = "File not found.", data = new { } });
            }
        }

        // Actual file download operation
        /*
         下载测试程式
        testProgramFile:程式文件
        programDriectory:程式目录
         */
        [HttpGet("download")]
        public IActionResult DownloadTestProgramFile(string testProgramFile, string programDriectory)
        {
            try
            {
                //var filePath = Path.Combine(_uploadFolderPath, fileName);
                // 解码路径
                string decodedPath = WebUtility.UrlDecode($@"{_testProgramPath}\{programDriectory}\{testProgramFile}");

                if (!System.IO.File.Exists(decodedPath))
                {
                    return NotFound(new { code = 404, message = "File not found.", data = new { } });
                }

                var stream = new FileStream(decodedPath, FileMode.Open, FileAccess.Read);
                return new FileStreamResult(stream, "application/octet-stream")
                {
                    FileDownloadName = testProgramFile
                };
            }
            catch (Exception ex)
            {
                // 增加更详细的错误日志
                Console.WriteLine($"Error: {ex.GetType().FullName}: {ex.Message}");
                Console.WriteLine($"Stack Trace: {ex.StackTrace}");

                // 记录到日志文件或其他监控工具(根据您的日志配置)
                // Logger.LogError(ex, "Error listing files");

                return StatusCode(500, new { code = 500, message = "Internal Server Error.", details = ex.Message });
            }

        }

        /// <summary>
        /// 上传测试程序块
        /// </summary>
        /// <param name="testProgramFile">测试程式文件</param>
        /// <param name="programDriectory">文件上传目录</param>
        /// <param name="fileName">文件名</param>
        /// <param name="chunkIndex">文件对应块指针</param>
        /// <param name="totalChunks">合总块</param>
        /// <returns></returns>
        [HttpPost("uploadtestProgramChunk")]
        public async Task<IActionResult> UploadtestProgramChunk(IFormFile testProgramFile, string programDriectory, string fileName, int chunkIndex, int totalChunks)
        {
            if (testProgramFile == null || testProgramFile.Length == 0)
            {
                return BadRequest(new { code = 400, message = "Upload failed. No chunk provided." });
            }

            string tempFilePath = Path.Combine($@"{_testProgramPath}\{programDriectory}", $"{fileName}.part{chunkIndex}");
            await using (var fileStream = System.IO.File.Create(tempFilePath))
            {
                await testProgramFile.CopyToAsync(fileStream);
            }

            fileChunkTracker.AddOrUpdate(fileName, 1, (key, oldValue) => oldValue + 1);
            if (fileChunkTracker[fileName] == totalChunks)
            {
                bool mergeSuccess = await MergeFileChunks(fileName, totalChunks, programDriectory);
                if (!mergeSuccess)
                {
                    return StatusCode(500, new { code = 500, message = "Error merging file chunks." });
                }

                fileChunkTracker.TryRemove(fileName, out _);
                return Ok(new { code = 200, message = "File uploaded and merged successfully." });
            }

            return Ok(new { code = 200, message = "Chunk uploaded successfully." });
        }

        /// <summary>
        /// 合并文件块
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="totalChunks">总块数</param>
        /// <param name="programDriectory">程式目录</param>
        /// <returns></returns>
        private async Task<bool> MergeFileChunks(string fileName, int totalChunks, string programDriectory)
        {
            string finalFilePath = Path.Combine($@"{_testProgramPath}\{programDriectory}", fileName);
            try
            {
                // Check if all chunk files exist before starting to merge
                for (int i = 0; i < totalChunks; i++)
                {
                    string tempFilePath = Path.Combine($@"{_testProgramPath}\{programDriectory}", $"{fileName}.part{i}");
                    if (!System.IO.File.Exists(tempFilePath))
                    {
                        Console.WriteLine($"Missing chunk: {tempFilePath}");
                        return false; // If any chunk is missing, abort the merge
                    }
                }

                await using (var finalStream = new FileStream(finalFilePath, FileMode.Create))
                {
                    for (int i = 0; i < totalChunks; i++)
                    {
                        string tempFilePath = Path.Combine($@"{_testProgramPath}\{programDriectory}", $"{fileName}.part{i}");
                        await using (var sourceStream = new FileStream(tempFilePath, FileMode.Open))
                        {
                            await sourceStream.CopyToAsync(finalStream);
                        }
                        System.IO.File.Delete(tempFilePath); // Delete the chunk file after it's been merged
                    }
                }
                return true; // All chunks have been merged successfully
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occurred while merging chunks: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 合并单元
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="totalChunks">总块数</param>
        /// <param name="programDriectory">程式目录</param>
        /// <returns></returns>
        [HttpPost("mergeChunks")]
        public async Task<IActionResult> MergeChunks(string fileName, int totalChunks, string programDriectory)
        {
            bool mergeSuccess = await MergeFileChunks(fileName, totalChunks, programDriectory);
            if (!mergeSuccess)
            {
                return StatusCode(500, new { code = 500, message = "Error merging file chunks." });
            }

            return Ok(new { code = 200, message = "File merged successfully." });
        }

        /// <summary>
        /// 列出下载程式清单
        /// </summary>
        /// <param name="programDriectory">程式目录</param>
        /// <returns></returns>
        [HttpGet("listdownFilePath")]
        public IActionResult ListDownloadableTestProgramFiles(string programDriectory)
        {
            try
            {
                // 解码路径
                string decodedPath = WebUtility.UrlDecode($@"{_testProgramPath}\{programDriectory}");

                if (!Directory.Exists(decodedPath))
                {
                    return new JsonResult(new { code = 404, message = "Upload folder not found." }) { StatusCode = StatusCodes.Status404NotFound };
                }

                var files = Directory.GetFiles(decodedPath, "*.*", SearchOption.AllDirectories)
                                     .Select(file => file.Replace(decodedPath, "").TrimStart(Path.DirectorySeparatorChar))
                                     .ToList();

                return new JsonResult(new { code = 200, message = "File list retrieved successfully.", data = new { files } }) { StatusCode = StatusCodes.Status200OK };
            }
            catch (Exception ex)
            {
                // 增加更详细的错误日志
                Console.WriteLine($"Error: {ex.GetType().FullName}: {ex.Message}");
                Console.WriteLine($"Stack Trace: {ex.StackTrace}");

                // 记录到日志文件或其他监控工具(根据您的日志配置)
                // Logger.LogError(ex, "Error listing files");

                return StatusCode(500, new { code = 500, message = "Internal Server Error.", details = ex.Message });
            }
        }
    }
}

 

import configparser
import logging
import sys
import time  # 修改这里
#import time as time_module  # 修改这里,避免命名冲突
import requests
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QProgressBar, QLabel, QDesktopWidget, \
    QMessageBox
from PyQt5.QtCore import QThread, pyqtSignal, Qt, QPoint
import os
import platform
import subprocess


class DownloadThread(QThread):
    progress_updated = pyqtSignal(int)
    speed_updated = pyqtSignal(str)
    download_completed = pyqtSignal()  # 新信号,表示下载完成
    current_file = pyqtSignal(str)  # 新增信号,传递当前下载文件的名称
    # 其他信号保持不变
    error_occurred = pyqtSignal()  # 新增信号,表示发生了错误

    def __init__(self, url, params_list, save_path_prefix):
        super().__init__()
        self.url = url
        self.params_list = params_list  # 现在是参数列表,每个元素是一个文件的参数

        self.save_path_prefix = save_path_prefix.replace("\\", "/")  # 确保使用正斜杠

    #执行
    def run(self):
        for params in self.params_list:
            # 用于Windows路径和兼容UNIX-like系统的路径处理
            file_path = params['testProgramFile'].replace("\\", "/")
            self.current_file.emit(file_path)  # 发出当前下载文件的名称
            # 检查文件路径中是否包含目录
            if "/" in file_path:
                # 存在目录,创建目录结构
                full_path = os.path.join(self.save_path_prefix, file_path)
                directory = os.path.dirname(full_path)
                if not os.path.exists(directory):
                    os.makedirs(directory, exist_ok=True)
            else:
                # 文件不包含目录,直接保存到根目录下
                full_path = os.path.join(self.save_path_prefix, file_path)

            try:
                with requests.get(self.url, params=params, stream=True) as r:
                    r.raise_for_status()
                    total_length = int(r.headers.get('content-length', 0))
                    download_length = 0
                    start_time = time.time()
                    with open(full_path, 'wb') as f:
                        for chunk in r.iter_content(chunk_size=1024):
                            if chunk:
                                f.write(chunk)
                                download_length += len(chunk)
                                if total_length > 0:
                                    progress = int(100 * download_length / total_length)
                                    self.progress_updated.emit(progress)  # 发出进度更新信号

                                elapsed_time = time.time() - start_time
                                if elapsed_time > 0:
                                    speed = download_length / elapsed_time
                                    self.speed_updated.emit(f"{speed / 1024:.2f} KB/s")  # 发出速度更新信号
            except Exception as e:
                print(f"下载{file_path}失败: {e}")
                self.error_occurred.emit()

        self.download_completed.emit()

        # 检查操作系统,如果不是Windows,则执行chmod命令
        print(platform.system())
        if platform.system() != "Windows":
            try:
                # 构建命令字符串
                cmd = f"chmod 777 {self.save_path_prefix} -R"
                subprocess.run(cmd, shell=True, check=True)
            except subprocess.CalledProcessError as e:
                print(f"修改权限失败: {e}")

    # def run(self):
    #     try:
    #         for params in self.params_list:
    #             file_name = params['testProgramFile']
    #             self.current_file.emit(file_name)  # 发出当前文件名信号
    #             save_path = f"{self.save_path_prefix}{file_name}"
    #             try:
    #                 with requests.get(self.url, params=params, stream=True) as r:
    #                     r.raise_for_status()  # 确保请求成功
    #                     total_length = int(r.headers.get('content-length'))
    #                     download_length = 0
    #                     start_time = time.time()
    #                     with open(save_path, 'wb') as f:
    #                         for chunk in r.iter_content(chunk_size=1024):
    #                             if chunk:
    #                                 f.write(chunk)
    #                                 download_length += len(chunk)
    #                                 progress = int(100 * download_length / total_length)
    #                                 self.progress_updated.emit(progress)
    #
    #                                 elapsed_time = time.time() - start_time
    #                                 if elapsed_time > 0:
    #                                     speed = download_length / elapsed_time
    #                                     self.speed_updated.emit(f"{speed / 1024:.2f} KB/s")
    #             except Exception as e:
    #                 print(f"下载{file_name}失败: {e}")
    #
    #         self.download_completed.emit()  # 下载完成后发出信号
    #
    #     except Exception as e:
    #         print(f"下载过程中发生错误: {e}")
    #         self.error_occurred.emit()


class MainWindow(QWidget):
    # 定义颜色代码
    COLOR_SUCCESS = "\033[1;32;43m"
    COLOR_ERROR = "\033[1;31m"
    COLOR_RESET = "\033[0m"

    def __init__(self):
        super().__init__()
        self.initUI()
        self.start_download()  # 添加这行代码来在窗口初始化后自动开始下载
        self.config = configparser.ConfigParser()

        # 生成日志信息
        self.logger = logging.getLogger('my_logger')  # 步骤1 创建日志记录器
        self.logger.setLevel(logging.DEBUG)  # 步骤2 将指定日志级别
        self.file_handler = logging.FileHandler('log/log.txt')  # 步骤3 创建文件处理器
        self.formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')  # 步骤4 创建格式化器
        self.file_handler.setFormatter(self.formatter)  # 步骤4 将格式化器添加到处理器
        self.logger.addHandler(self.file_handler)  # 步骤5 将处理器添加到日志记录器

        # 读取配置
        self.config.read('./Conf/config.conf', encoding='utf-8')  # 读取配置文件,如果配置文件不存在则创建

        # 读取Test_WebApi接口配置
        self.TestWebApi = self.config.get('TestWepApi', 'url')


    def initUI(self):
        self.setWindowTitle('File Downloader')
        self.setGeometry(100, 100, 400, 200)
        self.setWindowFlags(Qt.FramelessWindowHint)  # 设置为无边框窗口

        self.layout = QVBoxLayout()

        self.progress_bar = QProgressBar(self)
        self.speed_label = QLabel('Speed: 0 KB/s', self)
        self.current_file_label = QLabel('Current File: None', self)  # 新增标签
        #self.download_button = QPushButton('Download', self)
        #self.download_button.clicked.connect(self.start_download)

        self.layout.addWidget(self.progress_bar)
        self.layout.addWidget(self.speed_label)
        self.layout.addWidget(self.current_file_label)  # 将新标签添加到布局
        #self.layout.addWidget(self.download_button)

        self.setLayout(self.layout)
        self.centerWindow()#窗体居中显示

        self.oldPos = self.pos()

    def mousePressEvent(self, event):
        self.oldPos = event.globalPos()

    def mouseMoveEvent(self, event):
        delta = QPoint(event.globalPos() - self.oldPos)
        self.move(self.x() + delta.x(), self.y() + delta.y())
        self.oldPos = event.globalPos()

    #获取文件列表
    def get_file_list(self):
        url = f'{self.TestWebApi}/TestProgramFileManager/listdownFilePath'
        params = {'programDriectory': 'Online_UpdateProgram\\X86_UOS'}
        try:
            response = requests.get(url, params=params)
            response.raise_for_status()  # 这将抛出异常,如果请求返回了一个错误
            file_list = response.json().get('data', {}).get('files', [])
            return file_list
        except requests.RequestException as e:
            #print(f"获取文件列表失败: {e}")
            self.ShowLog(f"获取文件列表失败: {e}",False)
            return []

    #执行文件下载
    # MainWindow中start_download方法的修改
    def start_download(self):
        try:
            file_list = self.get_file_list()
            if not file_list:
                #print("文件列表为空,无法下载")
                self.ShowLog("文件列表为空,无法下载",False)
                return

            params_list = [{'testProgramFile': file_name, 'programDriectory': 'Online_UpdateProgram\\X86_UOS'} for
                           file_name in file_list]
            self.download_thread = DownloadThread(f'{self.TestWebApi}/TestProgramFileManager/download',
                                                  params_list, "")
            self.download_thread.progress_updated.connect(self.progress_bar.setValue)
            self.download_thread.speed_updated.connect(self.speed_label.setText)
            self.download_thread.current_file.connect(self.current_file_label.setText)  # 连接新信号
            self.download_thread.start()

            # 获取文件列表和初始化下载线程的代码保持不变
            self.download_thread.download_completed.connect(self.on_download_completed)
            self.download_thread.error_occurred.connect(self.on_error_occurred)
        except Exception as e:
            self.ShowLog(f"下载失败: {e}",False)
            #print(f"下载失败: {e}")

    #显示当前下载的文件
    def update_current_file_label(self, file_name):
        # 设置标签的文本
        self.current_file_label.setText(f"Current File: {file_name}")
        # 设置工具提示以显示完整的文件名
        self.current_file_label.setToolTip(file_name)

    #窗体居中显示
    def centerWindow(self):
        screen = QDesktopWidget().screenGeometry()  # 获取屏幕尺寸
        # 设置窗口宽度为屏幕宽度的1/3,高度为屏幕高度的1/12
        width = screen.width() * 2 / 3
        height = screen.height() * 1 / 15
        self.setFixedSize(width, height)  # 设置固定大小

        qr = self.frameGeometry()  # 获取主窗口的矩形框架
        cp = screen.center()  # 获取显示屏幕的中心点
        qr.moveCenter(cp)  # 将窗口框架的中心点移动到屏幕的中心位置
        self.move(qr.topLeft())  # 将窗口的左上角移动到矩形框架的左上角,实际上就是将窗口居中

        qr = self.frameGeometry()  # 获取主窗口的矩形框架
        cp = QDesktopWidget().availableGeometry().center()  # 获取显示屏幕的中心点
        qr.moveCenter(cp)  # 将窗口框架的中心点移动到屏幕的中心位置
        self.move(qr.topLeft())  # 将窗口的左上角移动到矩形框架的左上角,实际上就是将窗口居中

    def on_download_completed(self):
        QApplication.exit(0)  # 下载完成后正常退出

    def on_error_occurred(self):
        QApplication.exit(1)  # 发生错误时退出并返回1

    # 日志
    def ShowLog(self, log, is_success):
        try:
            if is_success:
                color = self.COLOR_SUCCESS
                self.logger.info(log)
            else:
                color = self.COLOR_ERROR
                self.logger.error(log)
                # QMessageBox.critical(self, '系统提醒', f"{log}", QMessageBox.Yes, QMessageBox.Yes)
            print(f"{color}{log}{self.COLOR_RESET}")
        except Exception as e:
            QMessageBox.critical(self, '系统提醒', f"{log}", QMessageBox.Yes, QMessageBox.Yes)
            print(f"{self.COLOR_ERROR}{e}{self.COLOR_RESET}")
            sys.exit(1)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MainWindow()
    ex.show()
    sys.exit(app.exec_())

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

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

相关文章

【鸿蒙开发】第二十章 Camera相机服务

1 简介 开发者通过调用Camera Kit(相机服务)提供的接口可以开发相机应用&#xff0c;应用通过访问和操作相机硬件&#xff0c;实现基础操作&#xff0c;如预览、拍照和录像&#xff1b;还可以通过接口组合完成更多操作&#xff0c;如控制闪光灯和曝光时间、对焦或调焦等。 2 …

js canvas实现裁剪图片并下载

简历上给自己挖的坑&#xff0c;面试被拷打&#xff0c;早就该填了T.T 参考&#xff1a;【js canvas实现图片裁剪】 https://www.bilibili.com/video/BV1QK411d7n1/?share_sourcecopy_web&vd_sourcebf743b20b76eab11028ba2fb05f056b4 效果 思路 组成&#xff1a; 上传文…

8. Spring Boot 配置文件

源码地址&#xff1a;SpringBoot_demo 本篇文章内容源码位于上述地址的com/chenshu/springboot_demo/config包下 1. 配置文件是什么 上节说到&#xff0c;Spring Boot的项目分为三个部分&#xff1a;源代码目录、资源目录、单元测试目录。 而配置文件的位置就位于资源目录res…

【竞技宝jjb.lol】LOL:T1成功击败HLE晋级MSI!

北京时间2024年4月13日,英雄联盟LCK2024春季季后赛继续进行,昨天迎来败者组决赛HLE对阵T1。本场比赛HLE率先拿下一局之后,T1连续两局在后期决策上碾压HLE拿到赛点,第四局zeus祭出上单VN在中期杀穿HLE后排,最终T1以3-1的比分击败HLE晋级春季决赛,同时也拿到了MSI的参赛资格。以下…

CSS3 常用样式

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 ✍CSS3 常用样式&#x1f48e;1 CSS3 新增选择器&#x1f339;1.1 属性选择器…

Python匿名函数4不要

当你需要完成一件小工作时&#xff0c;在本地环境中使用这个函数&#xff0c;可以让工作如此得心应手&#xff0c;它就是Lambda 函数。 Lambda 函数是 Python 中的匿名函数。有些人将它们简称为lambdas&#xff0c;它们的语法如下&#xff1a; lambda arguments: expressionl…

拥有了这24个Python接单平台,你就拥有了“钞能力”

学Python能兼职挣米吗&#xff1f;怎么挣&#xff1f; 一、Python兼职种类&#xff1a; 接私活刚学会python那会&#xff0c;就有认识的朋友介绍做一个网站的私活&#xff0c;当时接单赚了4K&#xff0c;后又自己接过开发网站后台接口、做数据处理等事情&#xff0c;都赚了一…

Python实现外观模式、桥接模式、组合模式和享元模式

今天介绍四种结构型设计模式&#xff1a;外观模式、桥接模式、组合模式和享元模式 外观模式 外观模式&#xff08;Facade Pattern&#xff09;&#xff0c;它为子系统提供一个统一的接口&#xff0c;使得子系统更加容易使用。 在Python中&#xff0c;我们可以通过定义一个外…

记录-若依前端集成markdown文档,自动生成文档目录

使用版本: vue 2.6.12 html-loader 1.3.2 markdown-loader 6.0.0 github-markdown-css ^5.5.1 highlight.js 9.18.5 webpack 4.47.x 一.引入loder插件&#xff0c;html-loader和markdown-loader //安装 pnpm install html-loader --save ; pnpm install markdown-loader --sa…

Zynq学习笔记--AXI 总线概述

目录 1. AXI总线概述 1.1 主要特点 1.2 通道功能 1.3 信号概览 2. AXI Interconnect 2.1 信号说明 2.2 内部结构 3. PS-PL AXI Interface 3.1 AXI FPD/LFP/ACP 3.2 Address Editor 3.3 地址空间 3.4 AXI-DDR 4. 通过ILA观察AXI信号 4.1 AXI 读通道 1. AXI总线概述…

头歌-机器学习 第15次实验 朴素贝叶斯分类器

第1关:条件概率 任务描述 本关任务:根据本节课所学知识完成本关所设置的选择题。 相关知识 为了完成本关任务,你需要掌握条件概率。 条件概率 朴素贝叶斯分类算法是基于贝叶斯定理与特征条件独立假设的分类方法,因此想要了解朴素贝叶斯分类算法背后的算法原理,就不得…

STM32-看门狗

1、看门狗是什么&#xff1a;就是一个向下定时器&#xff0c;定时时间一到&#xff0c;就会触发一个向下的复位的中断&#xff0c;使单片机开始工作 2、作用&#xff1a;MCU微控制器构成的微型计算机系统中&#xff0c;由于微控制器的工作常常会受到来自外界电磁场的干 扰,造成…

PostgreSQL入门到实战-第二十六弹

PostgreSQL入门到实战 PostgreSQL中数据分组操作(一)官网地址PostgreSQL概述PostgreSQL中GROUP BY命令理论PostgreSQL中GROUP BY命令实战更新计划 PostgreSQL中数据分组操作(一) 如何使用PostgreSQL GROUP BY子句将行分组。 官网地址 声明: 由于操作系统, 版本更新等原因, 文…

Transformer 结构浅析

Transformer 结构浅析 文章目录 Transformer 结构浅析Transformer 网络结构编码器位置编码多头注意力层Add&NormFeed Forward 解码器带掩码的多头注意力层多头注意力层 预测 Transformer 网络结构 Transformer模型的网络结构如图&#xff0c;且transformer结构主要分为两部…

编曲知识18:EQ均衡器 齿音处理 呼吸音处理 口水音处理

EQ均衡器 齿音处理 呼吸音处理 口水音处理小鹅通-专注内容付费的技术服务商https://app8epdhy0u9502.pc.xiaoe-tech.com/live_pc/l_66151c90e4b092c1187ac699?course_id=course_2XLKtQnQx9GrQHac7OPmHD9tqbv 均衡器 均衡器 Equalizer(简称EQ) 人耳接受频率:20hz—20khz …

python基础——类型注解【变量,函数,Union】

&#x1f4dd;前言&#xff1a; 上一篇文章Python基础——面相对象的三大特征提到&#xff0c;python中的多态&#xff0c;python中&#xff0c;类型是动态的&#xff0c;这意味着我们不需要在声明变量时指定其类型。然而&#xff0c;这可能导致运行时错误&#xff0c;因为我们…

【每日一算】冒泡算法

冒泡算法就是给数据排序的意思。比如说升序&#xff0c;17&#xff0c;8&#xff0c;9&#xff0c;28&#xff0c;5.升序之后的结果就是5&#xff0c;8&#xff0c;9&#xff0c;17&#xff0c;28. 从我们的大脑思维来看&#xff0c;结果一眼就有了&#xff0c;可是机器要怎么才…

论文阅读:Polyp-PVT: Polyp Segmentation with PyramidVision Transformers

这篇论文提出了一种名为Polyp-PVT的新型息肉分割框架&#xff0c;该框架采用金字塔视觉变换器&#xff08;Pyramid Vision Transformer, PVT&#xff09;作为编码器&#xff0c;以显式提取更强大的特征。本模型中使用到的关键技术有三个&#xff1a;渐进式特征融合、通道和空间…

Linux 【进程】

什么是进程 Linux中的进程是指正在运行的程序实例。每个进程都是操作系统内部管理的独立实体&#xff0c;具有自己的地址空间、代码、数据和打开的文件等资源。进程是并发执行的基本单位&#xff0c;可以同时运行多个进程。 Linux中的进程通过创建父子关系形成一个进程树。当一…

软件测试20个基础面试题及答案

什么是软件测试&#xff1f; 答案&#xff1a;软件测试是指在预定的环境中运行程序&#xff0c;为了发现软件存在的错误、缺陷以及其他不符合要求的行为的过程。 软件测试的目的是什么&#xff1f; 答案&#xff1a;软件测试的主要目的是保证软件的质量&#xff0c;并尽可能…