如何制作自动安装Python与PostgreSQL的MSI安装包及Tkinter问题解决
自动安装Python和PostgreSQL的Tkinter安装程序问题解决
问题概述
- 执行Python安装代码时,后台弹出UAC提示导致Tkinter窗口无响应
- 执行PostgreSQL安装代码时触发
OSError: [WinError 740] 要求权限提升错误
相关代码
Python安装代码
python_url = "https://www.python.org/ftp/python/3.10.0/python-3.10.0-amd64.exe" ssl_context = ssl.create_default_context() ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE installer_path = "python-3.10.0-amd64.exe" with urllib.request.urlopen(python_url, context=ssl_context) as response, open(installer_path, 'wb') as installer_file: installer_file.write(response.read()) process = subprocess.run([installer_path, '/quiet', 'InstallAllUsers=1', 'PrependPath=1'])
PostgreSQL安装代码
download_url = "https://sbp.enterprisedb.com/getfile.jsp?fileid=1258893" download_path = "postgresql-installer.exe" response = requests.get(download_url, stream=True) with open(download_path, 'wb') as file: for chunk in response.iter_content(chunk_size=1024): if chunk: file.write(chunk) if os.path.exists(download_path): install_command = ['runas', '/user:Administrator', download_path, "/SILENT", "/COMPONENTS=postgis"] install_process = subprocess.run(install_command, capture_output=True, text=True)
报错栈信息
Exception in Tkinter callback Traceback (most recent call last): File "C:\Program Files\Python310\lib\tkinter\_init_.py", line 1921, in __call__ return self.func(*args) File "C:\Program Files\Python310\lib\tkinter\_init_.py", line 839, in callit func(*args) File "C:\Users\cybrosys\Music\cyllo_installer.py", line 588, in execute_commands self.execute_command(cmd, admin_passd, flag_value, value) File "C:\Users\cybrosys\Music\cyllo_installer.py", line 709, in execute_command install_process = subprocess.run(install_command, capture_output=True, text=True) File "C:\Program Files\Python310\lib\subprocess.py", line 501, in run with Popen(*popenargs, **kwargs) as process: File "C:\Program Files\Python310\lib\subprocess.py", line 966, in __init__ self._execute_child(args, executable, preexec_fn, close_fds, File "C:\Program Files\Python310\lib\subprocess.py", line 1435, in _execute_child hp, ht, pid, tid = _winapi.CreateProcess(executable, args, OSError: [WinError 740] The requested operation requires elevation
解决方案
1. 解决Tkinter窗口无响应问题
原代码用subprocess.run()是阻塞式调用,UAC弹窗出现时会卡住Tkinter主线程,导致UI无响应。解决方式是将安装逻辑放到独立线程中执行,避免阻塞事件循环:
import threading import subprocess import ssl import urllib.request def install_python(): python_url = "https://www.python.org/ftp/python/3.10.0/python-3.10.0-amd64.exe" ssl_context = ssl.create_default_context() ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE installer_path = "python-3.10.0-amd64.exe" # 下载安装包 with urllib.request.urlopen(python_url, context=ssl_context) as response, open(installer_path, 'wb') as installer_file: installer_file.write(response.read()) # 非阻塞执行安装,线程内等待不影响UI process = subprocess.Popen([installer_path, '/quiet', 'InstallAllUsers=1', 'PrependPath=1']) process.wait() # 在Tkinter的按钮点击事件中启动线程 # 示例:button.config(command=lambda: threading.Thread(target=install_python, daemon=True).start())
2. 解决PostgreSQL安装权限不足问题
runas /user:Administrator的方式不可靠(账户可能改名/禁用,且无法静默输入密码),正确做法是通过系统API请求UAC提权,或直接让整个安装程序以管理员权限运行:
方式一:调用系统API提权执行安装
import ctypes from ctypes import wintypes import os import requests def run_as_admin(command): # 调用ShellExecuteEx实现UAC提权 ShellExecute = ctypes.windll.shell32.ShellExecuteW ShellExecute.argtypes = [ wintypes.HWND, wintypes.LPCWSTR, wintypes.LPCWSTR, wintypes.LPCWSTR, wintypes.LPCWSTR, wintypes.INT ] # SW_HIDE 静默执行,SW_SHOW 显示安装界面 return ShellExecute(None, "runas", command[0], " ".join(command[1:]), None, 0) # 修改PostgreSQL安装逻辑 download_url = "https://sbp.enterprisedb.com/getfile.jsp?fileid=1258893" download_path = "postgresql-installer.exe" response = requests.get(download_url, stream=True) with open(download_path, 'wb') as file: for chunk in response.iter_content(chunk_size=1024): if chunk: file.write(chunk) if os.path.exists(download_path): # 添加PostgreSQL静默安装参数,设置用户和密码 install_command = [ download_path, "/SILENT", "/COMPONENTS=postgis", "/PASSWORD=your_db_password", # 替换为实际密码 "/USERNAME=db_admin", # 替换为实际用户名 "/SUPERUSERNAME=postgres", # PostgreSQL默认超级用户 "/SUPERPASSWORD=postgres_pass" # 替换为超级用户密码 ] run_as_admin(install_command)
方式二:打包时要求管理员权限
如果用PyInstaller打包Tkinter程序,添加--uac-admin参数,这样用户启动exe时会直接触发UAC提权,后续安装无需重复请求:
pyinstaller --uac-admin --onefile your_installer.py
额外注意事项
- PostgreSQL静默安装参数需参考官方文档,确保参数正确(不同版本参数可能有差异)
- 下载文件时添加异常处理,避免网络错误导致程序崩溃
- 安装完成后可检查Python和PostgreSQL是否成功添加到系统路径
内容的提问来源于stack exchange,提问作者Ashique m
相关产品推荐
相关产品推荐

