如何编写Python脚本自动安装MiKTeX、Strawberry Perl及Python包
Python脚本实现依赖全自动安装方案
核心逻辑是前置检测+静默安装,全程无需用户手动点击安装向导,适配Windows环境(MiKTeX、Strawberry Perl为Windows端文档生成场景的常用依赖),已安装的依赖会自动跳过,避免重复执行安装流程。
前置准备
- 提前下载对应版本的MiKTeX、Strawberry Perl离线安装包,和你的Python脚本放在同一目录下分发,避免运行时网络波动导致安装失败
- 整理好你的脚本需要的所有Python第三方包清单
- 脚本开头默认申请管理员权限,满足系统软件安装的权限要求
完整实现代码
1. 基础导入与权限检测
把这段放在脚本最开头,自动申请管理员权限:
import sys import os import subprocess import importlib import ctypes import winreg def is_admin(): try: return ctypes.windll.shell32.IsUserAnAdmin() except Exception: return False # 非管理员运行时自动提权 if not is_admin(): print("[*] 正在申请管理员权限用于安装系统依赖...") ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join([f'"{arg}"' for arg in sys.argv]), None, 1) sys.exit(0)
2. Python依赖自动安装
自动检测Python包是否已安装,未安装则调用当前解释器对应的pip执行安装,避免安装到其他Python环境:
def install_python_pkg(import_name: str, pip_name: str = None): if pip_name is None: pip_name = import_name try: importlib.import_module(import_name) print(f"[√] Python依赖 {import_name} 已安装,跳过") return True except ImportError: print(f"[*] 正在安装Python依赖 {pip_name}...") install_cmd = [ sys.executable, "-m", "pip", "install", "--user", pip_name, "--no-warn-script-location" ] res = subprocess.run(install_cmd, capture_output=True, text=True) if res.returncode != 0: print(f"[×] {pip_name} 安装失败:{res.stderr}") return False print(f"[√] {pip_name} 安装完成") return True # 替换成你自己脚本需要的Python包列表:(导入名, pip安装名) required_python_pkgs = [ ("jinja2", None), ("pypandoc", None), ("markdown", None) ] for pkg_import, pkg_pip in required_python_pkgs: install_python_pkg(pkg_import, pkg_pip)
3. 系统软件检测与静默安装
自动检测MiKTeX、Strawberry Perl是否已安装,未安装则调用离线安装包执行无交互静默安装,安装完成后自动刷新系统环境变量,无需重启电脑:
def get_latest_system_path(): """从注册表读取最新的系统+用户环境变量Path,避免安装完环境变量不生效""" total_path = "" try: # 读取系统级Path with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment", access=winreg.KEY_READ) as key: sys_path = winreg.QueryValueEx(key, "Path")[0] # 读取用户级Path with winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Environment", access=winreg.KEY_READ) as key: user_path = winreg.QueryValueEx(key, "Path")[0] total_path = f"{sys_path};{user_path}" except Exception: pass return total_path def check_software_installed(soft_display_name: str, exe_filename: str): """通过环境变量和注册表双重检测软件是否已安装""" # 先查现有Path里有没有对应执行文件 for path_dir in os.environ.get("PATH", "").split(";"): if os.path.exists(os.path.join(path_dir, exe_filename)): print(f"[√] {soft_display_name} 已安装,跳过") return True # 查注册表卸载列表 try: with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall") as key: subkey_count = winreg.QueryInfoKey(key)[0] for i in range(subkey_count): subkey_name = winreg.EnumKey(key, i) with winreg.OpenKey(key, subkey_name) as subkey: try: current_name = winreg.QueryValueEx(subkey, "DisplayName")[0] if soft_display_name.lower() in current_name.lower(): print(f"[√] {soft_display_name} 已安装,跳过") return True except OSError: continue except Exception: pass return False def install_system_software(installer_path: str, soft_name: str, silent_args: list): """执行静默安装""" if not os.path.exists(installer_path): print(f"[×] 未找到{soft_name}安装包,请将对应离线安装包放到脚本同目录后重试") return False print(f"[*] 正在静默安装{soft_name},耗时可能较长,请不要关闭窗口...") install_cmd = [installer_path] + silent_args res = subprocess.run(install_cmd, capture_output=True, text=True) if res.returncode != 0: print(f"[×] {soft_name}安装失败:{res.stderr}") return False # 刷新当前进程的环境变量 os.environ["PATH"] = get_latest_system_path() print(f"[√] {soft_name}安装完成") return True # 安装MiKTeX,替换成你实际打包的安装包文件名 if not check_software_installed("MiKTeX", "pdflatex.exe"): miktex_installer = os.path.join(os.path.dirname(os.path.abspath(__file__)), "basic-miktex-x64.exe") install_system_software( miktex_installer, "MiKTeX", ["--unattended", "--auto-install=yes", "--add-path=yes"] ) # 安装Strawberry Perl,替换成你实际打包的安装包文件名 if not check_software_installed("Strawberry Perl", "perl.exe"): perl_installer = os.path.join(os.path.dirname(os.path.abspath(__file__)), "strawberry-perl-5.38.x64.msi") install_system_software( perl_installer, "Strawberry Perl", ["/silent", "/norestart", "ADD_TO_PATH=1"] )
后续优化建议
- 可以用PyInstaller把你的主脚本和上述安装逻辑打包成单个exe文件,用户拿到后只需要双击运行一次,所有依赖安装完成后自动进入你的文档生成功能
- MiKTeX安装时加的
--auto-install=yes参数会默认开启缺失宏包的静默下载,不会弹出确认窗口,适合无交互场景 - 如果需要适配32位系统,只需要替换对应32位的安装包,增加系统架构判断逻辑选择对应安装包即可
内容的提问来源于stack exchange,提问作者Mike K.
相关产品推荐
相关产品推荐

