build.bat参数解析兼容PowerShell+gitignore修正保留构建脚本
This commit is contained in:
+3
-1
@@ -4,7 +4,9 @@ __pycache__/
|
|||||||
*.pyo
|
*.pyo
|
||||||
*.egg-info/
|
*.egg-info/
|
||||||
dist/
|
dist/
|
||||||
build/
|
# PyInstaller output (在build目录内),但保留构建脚本
|
||||||
|
build/build/
|
||||||
|
build/*.log
|
||||||
|
|
||||||
# Virtual environment
|
# Virtual environment
|
||||||
venv/
|
venv/
|
||||||
|
|||||||
+117
@@ -0,0 +1,117 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
REM === WindowMsgBot 构建脚本 ===
|
||||||
|
REM 自动化打包和签名流程
|
||||||
|
REM 用法: build.bat /skip-cert /skip-sign
|
||||||
|
REM build.bat --skip-cert --skip-sign (PowerShell兼容)
|
||||||
|
REM build.bat skip-cert skip-sign (无前缀)
|
||||||
|
|
||||||
|
set "SCRIPT_DIR=%~dp0"
|
||||||
|
set "PROJECT_DIR=%SCRIPT_DIR%.."
|
||||||
|
set "PYTHON=%PROJECT_DIR%\.venv311\Scripts\python.exe"
|
||||||
|
set "PYINSTALLER=%PYTHON% -m PyInstaller"
|
||||||
|
|
||||||
|
set "SKIP_CERT=0"
|
||||||
|
set "SKIP_SIGN=0"
|
||||||
|
|
||||||
|
REM 解析参数(兼容 / -- 无前缀 三种写法)
|
||||||
|
:parse_args
|
||||||
|
if "%~1"=="" goto :start_build
|
||||||
|
set "_arg=%~1"
|
||||||
|
set "_arg=!_arg:/=!"
|
||||||
|
set "_arg=!_arg:--=!"
|
||||||
|
if "!_arg!"=="skip-cert" set "SKIP_CERT=1"
|
||||||
|
if "!_arg!"=="skip-sign" set "SKIP_SIGN=1"
|
||||||
|
shift
|
||||||
|
goto :parse_args
|
||||||
|
|
||||||
|
:start_build
|
||||||
|
echo === WindowMsgBot 构建脚本 ===
|
||||||
|
echo 项目目录: %PROJECT_DIR%
|
||||||
|
echo Python: %PYTHON%
|
||||||
|
echo.
|
||||||
|
|
||||||
|
REM 检查Python
|
||||||
|
if not exist "%PYTHON%" (
|
||||||
|
echo 错误: Python不存在: %PYTHON%
|
||||||
|
echo 请先创建虚拟环境
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 检查PyInstaller
|
||||||
|
"%PYTHON%" -c "import PyInstaller" >nul 2>&1
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo 安装PyInstaller...
|
||||||
|
"%PYTHON%" -m pip install pyinstaller
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 1. 生成证书(可选)
|
||||||
|
if "%SKIP_CERT%"=="0" (
|
||||||
|
echo 1. 生成自签名证书...
|
||||||
|
if exist "%SCRIPT_DIR%code_signing_cert.pfx" (
|
||||||
|
echo 证书已存在,跳过生成
|
||||||
|
) else (
|
||||||
|
powershell -ExecutionPolicy Bypass -File "%SCRIPT_DIR%generate_cert.ps1"
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo ⚠ 证书生成失败,继续构建...
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
echo 1. 跳过证书生成
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 2. 清理旧构建(只清理PyInstaller输出,保留build目录里的spec和hooks)
|
||||||
|
echo.
|
||||||
|
echo 2. 清理旧构建文件...
|
||||||
|
if exist "%PROJECT_DIR%\build\build" rmdir /s /q "%PROJECT_DIR%\build\build"
|
||||||
|
if exist "%PROJECT_DIR%\dist" rmdir /s /q "%PROJECT_DIR%\dist"
|
||||||
|
|
||||||
|
REM 3. PyInstaller打包
|
||||||
|
echo.
|
||||||
|
echo 3. PyInstaller打包...
|
||||||
|
|
||||||
|
REM 禁用 CUDA 防止 PyInstaller isolated 子进程 access violation 崩溃
|
||||||
|
set "PYTORCH_NO_CUDA_DISPATCH=1"
|
||||||
|
set "CUDA_VISIBLE_DEVICES="
|
||||||
|
|
||||||
|
cd /d "%PROJECT_DIR%"
|
||||||
|
"%PYINSTALLER%" "%SCRIPT_DIR%windowmsgbot.spec" --noconfirm --clean
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo 错误: PyInstaller打包失败!
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
echo ✓ 打包完成
|
||||||
|
|
||||||
|
REM 4. 签名(可选)
|
||||||
|
if "%SKIP_SIGN%"=="0" (
|
||||||
|
echo.
|
||||||
|
echo 4. 签名exe文件...
|
||||||
|
if exist "%SCRIPT_DIR%code_signing_cert.pfx" (
|
||||||
|
call "%SCRIPT_DIR%sign.bat"
|
||||||
|
) else (
|
||||||
|
echo ⚠ 证书不存在,跳过签名
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
echo.
|
||||||
|
echo 4. 跳过签名
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 5. 输出结果
|
||||||
|
echo.
|
||||||
|
echo 5. 构建结果...
|
||||||
|
if exist "%PROJECT_DIR%\dist\WindowMsgBot\WindowMsgBot.exe" (
|
||||||
|
echo ✓ 可执行文件: %PROJECT_DIR%\dist\WindowMsgBot\WindowMsgBot.exe
|
||||||
|
for %%A in ("%PROJECT_DIR%\dist\WindowMsgBot\WindowMsgBot.exe") do echo 大小: %%~zA 字节
|
||||||
|
echo ✓ 输出目录: %PROJECT_DIR%\dist\WindowMsgBot\
|
||||||
|
) else (
|
||||||
|
echo ✗ 可执行文件未生成
|
||||||
|
)
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo === 构建完成 ===
|
||||||
|
echo 输出目录: %PROJECT_DIR%\dist
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
# 生成自签名代码签名证书 - 降低360敏感度
|
||||||
|
# 使用方法: 以管理员身份运行 PowerShell, 执行 .\generate_cert.ps1
|
||||||
|
|
||||||
|
param(
|
||||||
|
[string]$CertPassword = "WindowMsgBot2026",
|
||||||
|
[string]$CertSubject = "CN=WindowMsgBot, O=WindowMsgBot Development",
|
||||||
|
[int]$ValidYears = 5
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Host "=== 生成自签名代码签名证书 ===" -ForegroundColor Cyan
|
||||||
|
|
||||||
|
# 1. 生成证书
|
||||||
|
Write-Host "1. 生成自签名证书..." -ForegroundColor Yellow
|
||||||
|
$cert = New-SelfSignedCertificate `
|
||||||
|
-Subject $CertSubject `
|
||||||
|
-Type CodeSigningCert `
|
||||||
|
-CertStoreLocation "Cert:\CurrentUser\My" `
|
||||||
|
-NotAfter (Get-Date).AddYears($ValidYears) `
|
||||||
|
-KeyAlgorithm RSA `
|
||||||
|
-KeyLength 2048 `
|
||||||
|
-HashAlgorithm SHA256 `
|
||||||
|
-FriendlyName "WindowMsgBot Code Signing Certificate"
|
||||||
|
|
||||||
|
if (-not $cert) {
|
||||||
|
Write-Error "证书生成失败!"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host " 证书指纹: $($cert.Thumbprint)" -ForegroundColor Green
|
||||||
|
|
||||||
|
# 2. 导出PFX文件
|
||||||
|
Write-Host "2. 导出PFX文件..." -ForegroundColor Yellow
|
||||||
|
$pfxPath = Join-Path $PSScriptRoot "code_signing_cert.pfx"
|
||||||
|
$password = ConvertTo-SecureString -String $CertPassword -Force -AsPlainText
|
||||||
|
|
||||||
|
Export-PfxCertificate `
|
||||||
|
-Cert $cert `
|
||||||
|
-FilePath $pfxPath `
|
||||||
|
-Password $password
|
||||||
|
|
||||||
|
Write-Host " PFX已保存: $pfxPath" -ForegroundColor Green
|
||||||
|
|
||||||
|
# 3. 导出CER文件(公钥)
|
||||||
|
Write-Host "3. 导出CER公钥文件..." -ForegroundColor Yellow
|
||||||
|
$cerPath = Join-Path $PSScriptRoot "code_signing_cert.cer"
|
||||||
|
Export-Certificate `
|
||||||
|
-Cert $cert `
|
||||||
|
-FilePath $cerPath
|
||||||
|
|
||||||
|
Write-Host " CER已保存: $cerPath" -ForegroundColor Green
|
||||||
|
|
||||||
|
# 4. 安装到受信任的根证书颁发机构
|
||||||
|
Write-Host "4. 安装到受信任的根证书颁发机构..." -ForegroundColor Yellow
|
||||||
|
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store(
|
||||||
|
"Root", "LocalMachine")
|
||||||
|
$store.Open("ReadWrite")
|
||||||
|
$store.Add($cert)
|
||||||
|
$store.Close()
|
||||||
|
|
||||||
|
Write-Host " 证书已安装到受信任的根证书存储" -ForegroundColor Green
|
||||||
|
|
||||||
|
# 5. 验证安装
|
||||||
|
Write-Host "5. 验证证书安装..." -ForegroundColor Yellow
|
||||||
|
$installed = Get-ChildItem -Path "Cert:\LocalMachine\Root" |
|
||||||
|
Where-Object { $_.Thumbprint -eq $cert.Thumbprint }
|
||||||
|
|
||||||
|
if ($installed) {
|
||||||
|
Write-Host " ✓ 证书已成功安装到受信任存储" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host " ⚠ 证书可能未安装到受信任存储" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
# 6. 输出证书信息
|
||||||
|
Write-Host "`n=== 证书信息 ===" -ForegroundColor Cyan
|
||||||
|
Write-Host "主题: $($cert.Subject)"
|
||||||
|
Write-Host "指纹: $($cert.Thumbprint)"
|
||||||
|
Write-Host "有效期: $($cert.NotBefore) 至 $($cert.NotAfter)"
|
||||||
|
Write-Host "用途: $($cert.EnhancedKeyUsageList.FriendlyName -join ', ')"
|
||||||
|
Write-Host "`nPFX密码: $CertPassword" -ForegroundColor Yellow
|
||||||
|
Write-Host "请妥善保管PFX文件和密码!" -ForegroundColor Red
|
||||||
|
|
||||||
|
# 7. 创建证书信息文件
|
||||||
|
Write-Host "7. 创建证书信息文件..." -ForegroundColor Yellow
|
||||||
|
$infoPath = Join-Path $PSScriptRoot "cert_info.txt"
|
||||||
|
@"
|
||||||
|
证书信息
|
||||||
|
========
|
||||||
|
主题: $($cert.Subject)
|
||||||
|
指纹: $($cert.Thumbprint)
|
||||||
|
有效期: $($cert.NotBefore) 至 $($cert.NotAfter)
|
||||||
|
PFX文件: code_signing_cert.pfx
|
||||||
|
CER文件: code_signing_cert.cer
|
||||||
|
PFX密码: $CertPassword
|
||||||
|
|
||||||
|
使用说明
|
||||||
|
========
|
||||||
|
1. PFX文件用于signtool签名
|
||||||
|
2. CER文件可分发给其他人验证签名
|
||||||
|
3. 证书已安装到本机受信任存储
|
||||||
|
"@ | Out-File -FilePath $infoPath -Encoding UTF8
|
||||||
|
|
||||||
|
Write-Host " 证书信息已保存: $infoPath" -ForegroundColor Green
|
||||||
|
|
||||||
|
Write-Host "`n=== 完成 ===" -ForegroundColor Cyan
|
||||||
|
Write-Host "下一步: 使用 sign.bat 脚本签名exe文件" -ForegroundColor Yellow
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
"""PyInstaller hook: 避免 easyocr 默认 hook 触发 collect_submodules('torch') 崩溃。
|
||||||
|
|
||||||
|
PyInstaller 默认 hook-easyocr.py 会调用 collect_submodules('easyocr'),
|
||||||
|
而 easyocr 内部 import torch,导致 isolated 子进程 access violation。
|
||||||
|
本 hook 只列出 easyocr 实际需要的子模块,避开 torch 引用。
|
||||||
|
"""
|
||||||
|
hiddenimports = [
|
||||||
|
'easyocr',
|
||||||
|
'easyocr.easyocr',
|
||||||
|
'easyocr.config',
|
||||||
|
'easyocr.detection',
|
||||||
|
'easyocr.recognition',
|
||||||
|
'easyocr.utils',
|
||||||
|
'easyocr.craft',
|
||||||
|
'easyocr.craft_utils',
|
||||||
|
'easyocr.imgproc',
|
||||||
|
'easyocr.dataset',
|
||||||
|
'easyocr.model',
|
||||||
|
'easyocr.model.vgg_model',
|
||||||
|
]
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
"""PyInstaller hook: 避免 collect_submodules('torch') 在 isolated 子进程中 access violation 崩溃。
|
||||||
|
|
||||||
|
PyInstaller 默认 hook-torch.py 调用 collect_submodules('torch') 遍历全部子模块,
|
||||||
|
在 torch 2.5+ 的 isolated 子进程中会触发 0xC0000005 access violation。
|
||||||
|
本 hook 直接列出实际需要的 torch 子模块,完全避开 collect_submodules。
|
||||||
|
"""
|
||||||
|
# 只列出 bot 实际引用的 torch 子模块(通过 import 分析确认)
|
||||||
|
hiddenimports = [
|
||||||
|
'torch',
|
||||||
|
'torch.nn',
|
||||||
|
'torch.nn.functional',
|
||||||
|
'torch.nn.modules',
|
||||||
|
'torch.nn.modules.activation',
|
||||||
|
'torch.nn.modules.conv',
|
||||||
|
'torch.nn.modules.linear',
|
||||||
|
'torch.nn.modules.module',
|
||||||
|
'torch.nn.modules.normalization',
|
||||||
|
'torch.nn.modules.padding',
|
||||||
|
'torch.nn.modules.pooling',
|
||||||
|
'torch.nn.modules.rnn',
|
||||||
|
'torch.nn.modules.sparse',
|
||||||
|
'torch.nn.modules.dropout',
|
||||||
|
'torch.nn.modules.batchnorm',
|
||||||
|
'torch.nn.modules.loss',
|
||||||
|
'torch.nn.modules.container',
|
||||||
|
'torch.nn.modules.flatten',
|
||||||
|
'torch.nn.modules.pixelshuffle',
|
||||||
|
'torch.nn.modules.upsampling',
|
||||||
|
'torch.nn.modules.channelshuffle',
|
||||||
|
'torch.cuda',
|
||||||
|
'torch.cuda.amp',
|
||||||
|
'torch.tensor',
|
||||||
|
'torch._C',
|
||||||
|
'torch._utils',
|
||||||
|
'torch.storage',
|
||||||
|
'torch.serialization',
|
||||||
|
'torch.types',
|
||||||
|
'torch.classes',
|
||||||
|
'torch.backends',
|
||||||
|
'torch.backends.cudnn',
|
||||||
|
]
|
||||||
+119
@@ -0,0 +1,119 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
REM === WindowMsgBot 签名脚本 ===
|
||||||
|
REM 使用自签名证书签名exe文件,降低360敏感度
|
||||||
|
REM 用法: sign.bat [exe路径]
|
||||||
|
|
||||||
|
set "SCRIPT_DIR=%~dp0"
|
||||||
|
set "PROJECT_DIR=%SCRIPT_DIR%.."
|
||||||
|
set "CERT_PFX=%SCRIPT_DIR%code_signing_cert.pfx"
|
||||||
|
set "CERT_PASS=WindowMsgBot2026"
|
||||||
|
set "OUTPUT_DIR=%PROJECT_DIR%\dist"
|
||||||
|
|
||||||
|
REM 如果没有指定exe文件,查找默认的exe(onedir模式在子目录中)
|
||||||
|
if "%~1"=="" (
|
||||||
|
if exist "%OUTPUT_DIR%\WindowMsgBot\WindowMsgBot.exe" (
|
||||||
|
set "EXE_PATH=%OUTPUT_DIR%\WindowMsgBot\WindowMsgBot.exe"
|
||||||
|
) else (
|
||||||
|
set "EXE_PATH=%OUTPUT_DIR%\WindowMsgBot.exe"
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
set "EXE_PATH=%~1"
|
||||||
|
)
|
||||||
|
|
||||||
|
echo === WindowMsgBot 代码签名 ===
|
||||||
|
echo.
|
||||||
|
|
||||||
|
REM 检查exe文件是否存在
|
||||||
|
if not exist "%EXE_PATH%" (
|
||||||
|
echo 错误: exe文件不存在: %EXE_PATH%
|
||||||
|
echo 请先运行 PyInstaller 构建: pyinstaller build/windowmsgbot.spec
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 检查证书文件是否存在
|
||||||
|
if not exist "%CERT_PFX%" (
|
||||||
|
echo 错误: 证书文件不存在: %CERT_PFX%
|
||||||
|
echo 请先运行证书生成脚本: powershell -ExecutionPolicy Bypass -File build\generate_cert.ps1
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 查找signtool.exe
|
||||||
|
set "SIGNTOOL="
|
||||||
|
for %%i in (
|
||||||
|
"%ProgramFiles%\Windows Kits\10\bin\x64\signtool.exe"
|
||||||
|
"%ProgramFiles(x86)%\Windows Kits\10\bin\x64\signtool.exe"
|
||||||
|
"%ProgramFiles%\Windows Kits\10\bin\x86\signtool.exe"
|
||||||
|
"%ProgramFiles(x86)%\Windows Kits\10\bin\x86\signtool.exe"
|
||||||
|
"%ProgramFiles%\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\signtool.exe"
|
||||||
|
) do (
|
||||||
|
if exist %%i (
|
||||||
|
set "SIGNTOOL=%%~i"
|
||||||
|
goto :found_sign
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 尝试从PATH查找
|
||||||
|
where signtool.exe >nul 2>&1
|
||||||
|
if %errorlevel% equ 0 (
|
||||||
|
set "SIGNTOOL=signtool.exe"
|
||||||
|
goto :found_sign
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 错误: 未找到 signtool.exe
|
||||||
|
echo 请安装 Windows SDK 或 Windows Kits
|
||||||
|
echo 下载地址: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:found_sign
|
||||||
|
echo 使用signtool: %SIGNTOOL%
|
||||||
|
echo.
|
||||||
|
|
||||||
|
REM 1. 签名exe
|
||||||
|
echo 1. 签名exe文件...
|
||||||
|
"%SIGNTOOL%" sign /f "%CERT_PFX%" /p "%CERT_PASS%" /tr http://timestamp.digicert.com /td sha256 /fd sha256 "%EXE_PATH%"
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo 错误: 签名失败!
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
echo ✓ 签名成功
|
||||||
|
|
||||||
|
REM 2. 验证签名
|
||||||
|
echo.
|
||||||
|
echo 2. 验证签名...
|
||||||
|
"%SIGNTOOL%" verify /pa "%EXE_PATH%"
|
||||||
|
if %errorlevel% equ 0 (
|
||||||
|
echo ✓ 签名验证通过
|
||||||
|
) else (
|
||||||
|
echo ⚠ 签名验证失败,但签名可能已应用
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 3. 显示签名信息
|
||||||
|
echo.
|
||||||
|
echo 3. 签名信息...
|
||||||
|
"%SIGNTOOL%" verify /v "%EXE_PATH%" 2>nul | findstr /i "Signing"
|
||||||
|
echo.
|
||||||
|
|
||||||
|
REM 4. 复制签名后的exe到项目根目录
|
||||||
|
echo 4. 复制签名后的exe...
|
||||||
|
copy "%EXE_PATH%" "%PROJECT_DIR%\WindowMsgBot_signed.exe" >nul
|
||||||
|
if %errorlevel% equ 0 (
|
||||||
|
echo ✓ 已复制到: %PROJECT_DIR%\WindowMsgBot_signed.exe
|
||||||
|
) else (
|
||||||
|
echo ⚠ 复制失败
|
||||||
|
)
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo === 完成 ===
|
||||||
|
echo 签名后的exe: %EXE_PATH%
|
||||||
|
echo 备份副本: %PROJECT_DIR%\WindowMsgBot_signed.exe
|
||||||
|
echo.
|
||||||
|
echo 注意: 自签名证书需要在目标机器上安装证书才能验证签名
|
||||||
|
echo 证书文件: %CERT_PFX%
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
# -*- mode: python ; coding: utf-8 -*-
|
||||||
|
# WindowMsgBot PyInstaller spec文件
|
||||||
|
# 用法: pyinstaller build/windowmsgbot.spec
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from PyInstaller.utils.hooks import collect_submodules, collect_data_files
|
||||||
|
|
||||||
|
# 项目根目录
|
||||||
|
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(SPEC)))
|
||||||
|
|
||||||
|
# 收集所有需要的子模块
|
||||||
|
hiddenimports = [
|
||||||
|
'uiautomation',
|
||||||
|
'win32gui',
|
||||||
|
'win32con',
|
||||||
|
'win32api',
|
||||||
|
'win32process',
|
||||||
|
'psutil',
|
||||||
|
'PIL',
|
||||||
|
'PIL.Image',
|
||||||
|
'PIL.ImageGrab',
|
||||||
|
'PIL.ImageEnhance',
|
||||||
|
'PIL.ImageFilter',
|
||||||
|
'easyocr',
|
||||||
|
'numpy',
|
||||||
|
'torch',
|
||||||
|
'torchvision',
|
||||||
|
'sklearn',
|
||||||
|
'sklearn.feature_extraction.text',
|
||||||
|
'sklearn.metrics.pairwise',
|
||||||
|
'jieba',
|
||||||
|
'customtkinter',
|
||||||
|
'comtypes',
|
||||||
|
'comtypes.client',
|
||||||
|
'win32com',
|
||||||
|
'win32com.client',
|
||||||
|
'pythoncom',
|
||||||
|
'pywintypes',
|
||||||
|
'ctypes',
|
||||||
|
'ctypes.wintypes',
|
||||||
|
'sqlite3',
|
||||||
|
'json',
|
||||||
|
'hashlib',
|
||||||
|
'difflib',
|
||||||
|
'unicodedata',
|
||||||
|
'signal',
|
||||||
|
'subprocess',
|
||||||
|
'threading',
|
||||||
|
'logging',
|
||||||
|
'traceback',
|
||||||
|
'faulthandler',
|
||||||
|
're',
|
||||||
|
'random',
|
||||||
|
'datetime',
|
||||||
|
'time',
|
||||||
|
'sys',
|
||||||
|
'os',
|
||||||
|
'io',
|
||||||
|
'math',
|
||||||
|
'struct',
|
||||||
|
'codecs',
|
||||||
|
'encodings',
|
||||||
|
'encodings.utf_8',
|
||||||
|
'encodings.gbk',
|
||||||
|
'encodings.gb2312',
|
||||||
|
'encodings.gb18030',
|
||||||
|
]
|
||||||
|
|
||||||
|
# 数据文件
|
||||||
|
datas = [
|
||||||
|
# 知识库目录
|
||||||
|
(os.path.join(PROJECT_ROOT, '知识库'), '知识库'),
|
||||||
|
# 偏旁库
|
||||||
|
(os.path.join(PROJECT_ROOT, 'unicode_radicals.md'), '.'),
|
||||||
|
# 配置文件
|
||||||
|
(os.path.join(PROJECT_ROOT, 'config.json'), '.'),
|
||||||
|
# EasyOCR worker脚本(作为数据文件,运行时提取)
|
||||||
|
(os.path.join(PROJECT_ROOT, 'easyocr_worker.py'), '.'),
|
||||||
|
# 其他必要文件
|
||||||
|
(os.path.join(PROJECT_ROOT, 'auto_reply.py'), '.'),
|
||||||
|
(os.path.join(PROJECT_ROOT, 'knowledge_base.py'), '.'),
|
||||||
|
(os.path.join(PROJECT_ROOT, 'config.py'), '.'),
|
||||||
|
(os.path.join(PROJECT_ROOT, 'gui.py'), '.'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# 收集easyocr数据文件
|
||||||
|
easyocr_datas = collect_data_files('easyocr')
|
||||||
|
datas.extend(easyocr_datas)
|
||||||
|
|
||||||
|
# 分析
|
||||||
|
a = Analysis(
|
||||||
|
[os.path.join(PROJECT_ROOT, 'main.py')],
|
||||||
|
pathex=[PROJECT_ROOT],
|
||||||
|
binaries=[],
|
||||||
|
datas=datas,
|
||||||
|
hiddenimports=hiddenimports,
|
||||||
|
hookspath=[os.path.join(PROJECT_ROOT, 'build', 'hooks')],
|
||||||
|
hooksconfig={},
|
||||||
|
runtime_hooks=[],
|
||||||
|
excludes=[
|
||||||
|
'tkinter.test',
|
||||||
|
'unittest',
|
||||||
|
'test',
|
||||||
|
'distutils',
|
||||||
|
'setuptools',
|
||||||
|
'pip',
|
||||||
|
'pkg_resources',
|
||||||
|
'pydoc',
|
||||||
|
'doctest',
|
||||||
|
'torch.autograd',
|
||||||
|
'torch.testing',
|
||||||
|
'torch.distributed',
|
||||||
|
'torch.fx',
|
||||||
|
'torch.jit',
|
||||||
|
'torch.onnx',
|
||||||
|
'torch.profiler',
|
||||||
|
'torch.sparse',
|
||||||
|
'torch.utils.benchmark',
|
||||||
|
'torch.utils.bottleneck',
|
||||||
|
'torch.utils.checkpoint',
|
||||||
|
'torch.utils.collect_env',
|
||||||
|
'torch.utils.cpp_extension',
|
||||||
|
'torch.utils.data',
|
||||||
|
'torch.utils.deterministic',
|
||||||
|
'torch.utils.dlpack',
|
||||||
|
'torch.utils.file_baton',
|
||||||
|
'torch.utils.hipify',
|
||||||
|
'torch.utils.jit',
|
||||||
|
'torch.utils.mobile_optimizer',
|
||||||
|
'torch.utils.model_zoo',
|
||||||
|
'torch.utils.show_pickle',
|
||||||
|
'torch.utils.tensorboard',
|
||||||
|
'torch.utils.throughput_benchmark',
|
||||||
|
],
|
||||||
|
noarchive=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
# 过滤掉不必要的大文件
|
||||||
|
a.datas = [d for d in a.datas if not d[0].endswith(('.pyc', '.pyo'))]
|
||||||
|
|
||||||
|
# PYZ - Python字节码
|
||||||
|
pyz = PYZ(a.pure)
|
||||||
|
|
||||||
|
# EXE - 主程序(onedir模式:只放脚本+PYZ,不嵌入binaries/data)
|
||||||
|
exe = EXE(
|
||||||
|
pyz,
|
||||||
|
a.scripts,
|
||||||
|
[],
|
||||||
|
exclude_binaries=True, # onedir关键:不嵌入二进制,交给COLLECT
|
||||||
|
name='WindowMsgBot',
|
||||||
|
debug=False,
|
||||||
|
bootloader_ignore_signals=False,
|
||||||
|
strip=False,
|
||||||
|
upx=False, # UPX对大型DLL(torch/scipy)常出问题,关掉
|
||||||
|
console=True,
|
||||||
|
disable_windowed_traceback=False,
|
||||||
|
argv_emulation=False,
|
||||||
|
target_arch=None,
|
||||||
|
codesign_identity=None,
|
||||||
|
entitlements_file=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
# COLLECT - 收集所有文件到输出目录
|
||||||
|
coll = COLLECT(
|
||||||
|
exe,
|
||||||
|
a.binaries,
|
||||||
|
a.datas,
|
||||||
|
strip=False,
|
||||||
|
upx=False,
|
||||||
|
name='WindowMsgBot',
|
||||||
|
)
|
||||||
Binary file not shown.
Reference in New Issue
Block a user