Release Python Program as exe

本文详细介绍了如何在Python 2.7环境下安装py2exe,并提供了常见问题的解决方案,如注册表设置及版本匹配等。此外还简要说明了如何使用py2exe将Python程序打包成exe文件。

py2exe 可以用来将python program 以exe的形式发布。

安装py2exe

对于python 3.x
pip install py2exe 可以直接安装

对于python 2.7, 需要下载exe安装,
https://sourceforge.net/projects/py2exe/files/py2exe/0.6.9/

这里详细记录一下python2.7下 py2exe的安装注意的问题
1. 安装时出现如下错误,
Python version 2.7 required, which was not found in the registry
解决:
copy下面的脚本,创建一个registry.py, 然后运行python registry.py

import sys

from _winreg import *

# tweak as necessary
version = sys.version[:3]
installpath = sys.prefix

regpath = "SOFTWARE\\Python\\Pythoncore\\%s\\" % (version)
installkey = "InstallPath"
pythonkey = "PythonPath"
pythonpath = "%s;%s\\Lib\\;%s\\DLLs\\" % (
    installpath, installpath, installpath
)

def RegisterPy():
    try:
        reg = OpenKey(HKEY_CURRENT_USER, regpath)
    except EnvironmentError as e:
        try:
            reg = CreateKey(HKEY_CURRENT_USER, regpath)
            SetValue(reg, installkey, REG_SZ, installpath)
            SetValue(reg, pythonkey, REG_SZ, pythonpath)
            CloseKey(reg)
        except:
            print "*** Unable to register!"
            return
        print "--- Python", version, "is now registered!"
        return
    if (QueryValue(reg, installkey) == installpath and
        QueryValue(reg, pythonkey) == pythonpath):
        CloseKey(reg)
        print "=== Python", version, "is already registered!"
        return
    CloseKey(reg)
    print "*** Unable to register!"
    print "*** You probably have another Python installation!"

if __name__ == "__main__":
    RegisterPy()
  1. 错误

    import py2exe_util
    ImportError: DLL load failed: %1 is not a valid Win32 application.

    解决: 这是安装错了py2exe的版本。 下载列表中的win64, amd64似乎不是指OS的版本。我PC是win64,但是安装win64版本有上述错误。安装py2exe-0.6.9.win32-py2.7.exe后解决了问题。

生成exe

按照http://www.py2exe.org/index.cgi/Tutorial#Step1中的guide 不再详述。
注意的问题:
如果生成的exe遇到local module 找不到的情况,
解决方案: 在所有subfolder中加上空白的 __init__.py

Reference

http://www.py2exe.org/

http://www.py2exe.org/index.cgi/Tutorial#Step1

PS D:\All-Project\pointlion-ui\pointlion-ui> npm install --legacy-peer-deps npm WARN EBADENGINE Unsupported engine { npm WARN EBADENGINE package: '@achrinza/node-ipc@9.2.2', npm WARN EBADENGINE required: { node: '8 || 10 || 12 || 14 || 16 || 17' }, npm WARN EBADENGINE current: { node: 'v20.13.1', npm: '10.5.2' } npm WARN EBADENGINE } npm WARN deprecated @types/minimatch@6.0.0: This is a stub types definition. minimatch provides its own type definitions, so you do not need this installed. npm WARN deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. npm WARN deprecated @npmcli/move-file@1.1.2: This functionality has been moved to @npmcli/fs npm WARN deprecated @babel/plugin-proposal-class-properties@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead. npm WARN deprecated lodash.isequal@4.5.0: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. npm WARN deprecated move-concurrently@1.0.1: This package is no longer supported. npm WARN deprecated stable@0.1.8: Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility npm WARN deprecated source-map-url@0.4.1: See https://github.com/lydell/source-map-url#deprecated npm WARN deprecated figgy-pudding@3.5.2: This module is no longer supported. npm WARN deprecated request-promise-native@1.0.9: request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142 npm WARN deprecated @hapi/bourne@1.3.2: This version has been deprecated and is no longer supported or maintained npm WARN deprecated @hapi/topo@3.1.6: This version has been deprecated and is no longer supported or maintained npm WARN deprecated eslint-loader@2.2.1: This loader has been deprecated. Please use eslint-webpack-plugin npm WARN deprecated rimraf@2.7.1: Rimraf versions prior to v4 are no longer supported npm WARN deprecated rimraf@2.7.1: Rimraf versions prior to v4 are no longer supported npm WARN deprecated rimraf@2.7.1: Rimraf versions prior to v4 are no longer supported npm WARN deprecated rimraf@2.7.1: Rimraf versions prior to v4 are no longer supported npm WARN deprecated rimraf@2.7.1: Rimraf versions prior to v4 are no longer supported npm WARN deprecated rimraf@2.7.1: Rimraf versions prior to v4 are no longer supported npm WARN deprecated rimraf@2.7.1: Rimraf versions prior to v4 are no longer supported npm WARN deprecated rimraf@2.7.1: Rimraf versions prior to v4 are no longer supported npm WARN deprecated rimraf@2.7.1: Rimraf versions prior to v4 are no longer supported npm WARN deprecated consolidate@0.15.1: Please upgrade to consolidate v1.0.0+ as it has been modernized with several long-awaited fixes implemented. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/consolidate for updates and release changelog npm WARN deprecated copy-concurrently@1.0.5: This package is no longer supported. npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated npm WARN deprecated har-validator@5.1.5: this library is no longer supported npm WARN deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported npm WARN deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported npm WARN deprecated abab@2.0.6: Use your platform's native atob() and btoa() methods instead npm WARN deprecated q@1.5.1: You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. npm WARN deprecated npm WARN deprecated (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) npm WARN deprecated domexception@1.0.1: Use your platform's native DOMException instead npm WARN deprecated source-map-resolve@0.5.3: See https://github.com/lydell/source-map-resolve#deprecated npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated npm WARN deprecated left-pad@1.3.0: use String.prototype.padStart() npm WARN deprecated w3c-hr-time@1.0.2: Use your platform's native performance.now() and performance.timeOrigin. npm WARN deprecated microargs@1.1.2: This project has been renamed to @pawelgalazka/cli-args. Install using @pawelgalazka/cli-args instead npm WARN deprecated html-webpack-plugin@3.2.0: 3.x is no longer supported npm WARN deprecated fs-write-stream-atomic@1.0.10: This package is no longer supported. npm WARN deprecated sane@4.1.0: some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added npm WARN deprecated microcli@1.3.3: This project has been renamed to @pawelgalazka/cli . Install using @pawelgalazka/cli instead npm WARN deprecated @hapi/address@2.1.4: Moved to 'npm install @sideway/address' npm WARN deprecated babel-eslint@10.1.0: babel-eslint is now @babel/eslint-parser. This package will no longer receive updates. npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 npm WARN deprecated runjs@4.4.2: This project has been renamed to 'tasksfile'. Install using 'npm install tasksfile' instead. npm WARN deprecated webpack-chain@6.5.1: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. npm WARN deprecated @hapi/hoek@8.5.1: This version has been deprecated and is no longer supported or maintained npm WARN deprecated @hapi/joi@15.1.1: Switch to 'npm install joi' npm WARN deprecated svgo@1.3.2: This SVGO version is no longer supported. Upgrade to v2.x.x. npm WARN deprecated vue@2.7.16: Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details. npm WARN deprecated highlight.js@9.18.5: Support has ended for 9.x series. Upgrade to @latest npm WARN deprecated eslint@7.15.0: This version is no longer supported. Please see https://eslint.org/version-support for other options. npm WARN deprecated core-js@2.6.12: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. npm WARN deprecated core-js@3.19.1: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. npm ERR! code 1 npm ERR! path D:\All-Project\pointlion-ui\pointlion-ui\node_modules\deasync npm ERR! command failed npm ERR! command C:\WINDOWS\system32\cmd.exe /d /s /c node ./build.js npm ERR! gyp info it worked if it ends with ok npm ERR! gyp info using node-gyp@10.1.0 npm ERR! gyp info using node@20.13.1 | win32 | ia32 npm ERR! gyp ERR! find Python npm ERR! gyp ERR! find Python Python is not set from command line or npm configuration npm ERR! gyp ERR! find Python Python is not set from environment variable PYTHON npm ERR! gyp ERR! find Python checking if the py launcher can be used to find Python 3 npm ERR! gyp ERR! find Python - executable path is "" npm ERR! gyp ERR! find Python - "" could not be run npm ERR! gyp ERR! find Python checking if "python3" can be used npm ERR! gyp ERR! find Python - executable path is "" npm ERR! gyp ERR! find Python - "" could not be run npm ERR! gyp ERR! find Python checking if "python" can be used npm ERR! gyp ERR! find Python - executable path is "" npm ERR! gyp ERR! find Python - "" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Users\16976\AppData\Local\Programs\Python\Python311\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Users\16976\AppData\Local\Programs\Python\Python311\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Program Files\Python311\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Program Files\Python311\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Users\16976\AppData\Local\Programs\Python\Python311-32\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Users\16976\AppData\Local\Programs\Python\Python311-32\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Program Files\Python311-32\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Program Files\Python311-32\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Program Files (x86)\Python311-32\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Program Files (x86)\Python311-32\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Users\16976\AppData\Local\Programs\Python\Python310\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Users\16976\AppData\Local\Programs\Python\Python310\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Program Files\Python310\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Program Files\Python310\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Users\16976\AppData\Local\Programs\Python\Python310-32\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Users\16976\AppData\Local\Programs\Python\Python310-32\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Program Files\Python310-32\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Program Files\Python310-32\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Program Files (x86)\Python310-32\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Program Files (x86)\Python310-32\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Users\16976\AppData\Local\Programs\Python\Python39\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Users\16976\AppData\Local\Programs\Python\Python39\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Program Files\Python39\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Program Files\Python39\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Users\16976\AppData\Local\Programs\Python\Python39-32\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Users\16976\AppData\Local\Programs\Python\Python39-32\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Program Files\Python39-32\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Program Files\Python39-32\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Program Files (x86)\Python39-32\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Program Files (x86)\Python39-32\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Users\16976\AppData\Local\Programs\Python\Python38\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Users\16976\AppData\Local\Programs\Python\Python38\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Program Files\Python38\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Program Files\Python38\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Users\16976\AppData\Local\Programs\Python\Python38-32\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Users\16976\AppData\Local\Programs\Python\Python38-32\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Program Files\Python38-32\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Program Files\Python38-32\python.exe" could not be run npm ERR! gyp ERR! find Python checking if Python is C:\Program Files (x86)\Python38-32\python.exe npm ERR! gyp ERR! find Python - version is "" npm ERR! gyp ERR! find Python - version is - should be >=3.6.0 npm ERR! gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED npm ERR! gyp ERR! find Python - "C:\Program Files (x86)\Python38-32\python.exe" could not be run npm ERR! gyp ERR! find Python npm ERR! gyp ERR! find Python ********************************************************** npm ERR! gyp ERR! find Python You need to install the latest version of Python. npm ERR! gyp ERR! find Python Node-gyp should be able to find and use Python. If not, npm ERR! gyp ERR! find Python you can try one of the following options: npm ERR! gyp ERR! find Python - Use the switch --python="C:\Path\To\python.exe" npm ERR! gyp ERR! find Python (accepted by both node-gyp and npm) npm ERR! gyp ERR! find Python - Set the environment variable PYTHON npm ERR! gyp ERR! find Python - Set the npm configuration variable python: npm ERR! gyp ERR! find Python npm config set python "C:\Path\To\python.exe" npm ERR! gyp ERR! find Python For more information consult the documentation at: npm ERR! gyp ERR! find Python https://github.com/nodejs/node-gyp#installation npm ERR! gyp ERR! find Python ********************************************************** npm ERR! gyp ERR! find Python npm ERR! gyp ERR! configure error npm ERR! gyp ERR! stack Error: Could not find any Python installation to use npm ERR! gyp ERR! stack at PythonFinder.fail (C:\Program Files (x86)\nodejs\node_modules\npm\node_modules\node-gyp\lib\find-python.js:306:11) npm ERR! gyp ERR! stack at PythonFinder.findPython (C:\Program Files (x86)\nodejs\node_modules\npm\node_modules\node-gyp\lib\find-python.js:164:17) npm ERR! gyp ERR! stack at process.processTicksAndRejections (node:internal/process/task_queues:95:5) npm ERR! gyp ERR! stack at async configure (C:\Program Files (x86)\nodejs\node_modules\npm\node_modules\node-gyp\lib\configure.js:27:18) npm ERR! gyp ERR! stack at async run (C:\Program Files (x86)\nodejs\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js:81:18) npm ERR! gyp ERR! System Windows_NT 10.0.22631 npm ERR! gyp ERR! command "C:\\Program Files (x86)\\nodejs\\node.exe" "C:\\Program Files (x86)\\nodejs\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild" npm ERR! gyp ERR! cwd D:\All-Project\pointlion-ui\pointlion-ui\node_modules\deasync npm ERR! gyp ERR! node -v v20.13.1 npm ERR! gyp ERR! node-gyp -v v10.1.0 npm ERR! gyp ERR! not ok npm ERR! Build failed npm ERR! A complete log of this run can be found in: C:\Users\16976\AppData\Local\npm-cache\_logs\2025-10-27T05_42_07_835Z-debug-0.log PS D:\All-Project\pointlion-ui\pointlion-ui> PS D:\All-Project\pointlion-ui\pointlion-ui>
10-28
<think> 我们使用PyInstaller来将Python脚本打包成可执行文件(EXE),并且确保它在所有环境(特别是Windows)中都能运行。以下是详细步骤和代码示例。 ### 步骤1:安装PyInstaller 首先,确保安装了PyInstaller。可以使用pip安装: ```bash pip install pyinstaller ``` ### 步骤2:创建打包脚本 我们将编写一个Python脚本,用于自动执行打包过程,并处理常见问题(如资源文件、隐藏导入等)。 ### 完整打包脚本 以下是一个完整的打包脚本,它处理了常见的兼容性问题,并支持包含资源文件。 ```python # build_exe.py import os import sys import subprocess import shutil from pathlib import Path def run_command(cmd): """运行命令并检查错误""" result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) if result.returncode != 0: print(f"命令执行失败: {cmd}") print(f"错误信息: {result.stderr}") sys.exit(1) return result def main(): # 获取当前工作目录 base_path = Path(__file__).parent.absolute() # 要打包的Python脚本 script_name = "your_script.py" # 替换为你的脚本文件名 # 检查脚本是否存在 if not (base_path / script_name).exists(): print(f"错误:找不到脚本 {script_name}") sys.exit(1) # 清理之前的构建 build_dir = base_path / "build" dist_dir = base_path / "dist" if build_dir.exists(): shutil.rmtree(build_dir) if dist_dir.exists(): shutil.rmtree(dist_dir) # 创建资源文件路径(如果有) data_dirs = [] # 示例:如果你的脚本需要'data'目录,则添加如下 # data_dirs.append(("data", "data")) # (源目录, 目标目录) # 构建PyInstaller命令 cmd = [ "pyinstaller", "--onefile", # 打包成单个exe文件 "--windowed", # 如果是GUI程序,使用此选项隐藏控制台窗口;如果是命令行程序则去掉 f"--name={Path(script_name).stem}", # 使用脚本名作为exe名 "--clean", # 清理临时文件 ] # 添加数据文件(资源) for src, dest in data_dirs: cmd.append(f"--add-data={src}{os.pathsep}{dest}") # 添加隐藏导入(如果有模块是动态导入的) # 例如:cmd.append("--hidden-import=module_name") # 添加图标(如果有) icon_path = base_path / "app_icon.ico" if icon_path.exists(): cmd.append(f"--icon={icon_path}") # 添加脚本路径 cmd.append(str(base_path / script_name)) # 运行打包命令 print("开始打包...") run_command(" ".join(cmd)) # 检查输出 exe_path = dist_dir / f"{Path(script_name).stem}.exe" if exe_path.exists(): print(f"打包成功!可执行文件位于: {exe_path}") else: print("打包失败,请检查错误信息。") if __name__ == "__main__": main() ``` ### 步骤3:处理资源文件 如果你的脚本使用了资源文件(如图片、数据文件等),需要在打包时包含它们。在`data_dirs`列表中添加元组,每个元组表示源目录(或文件)和打包后的目标目录。 例如,如果你的脚本中有一个`data`目录,打包后需要放在exe的同级目录下的`data`目录中,则添加: ```python data_dirs = [("data/*", "data")] ``` 在代码中访问这些资源时,需要使用以下方式获取正确的路径: ```python import sys import os def resource_path(relative_path): """ 获取资源的绝对路径。用于PyInstaller打包后定位资源文件。""" if hasattr(sys, '_MEIPASS'): base_path = sys._MEIPASS else: base_path = os.path.abspath(".") return os.path.join(base_path, relative_path) # 使用示例 data_file = resource_path("data/somefile.txt") ``` ### 步骤4:处理隐藏导入 如果程序使用了动态导入(例如通过`importlib`或插件系统),则需要在打包命令中通过`--hidden-import`指定这些模块。 ### 步骤5:运行打包脚本 将上述脚本保存为`build_exe.py`,并确保: 1. 将要打包的脚本(例如`your_script.py`)放在同一目录。 2. 如果有图标文件,命名为`app_icon.ico`并放在同一目录。 3. 如果有资源目录(如`data`),也放在同一目录。 然后运行: ```bash python build_exe.py ``` ### 步骤6:测试可执行文件 在`dist`目录下会生成一个单独的可执行文件。将其复制到没有Python环境的Windows机器上测试。 ### 注意事项 1. **防病毒软件误报**:打包后的exe可能被某些防病毒软件误报为病毒。可以通过代码签名缓解。 2. **文件路径**:在打包程序中,不要使用硬编码路径,使用`resource_path`函数。 3. **控制台与窗口模式**:命令行程序不要使用`--windowed`,GUI程序(如PyQt、Tkinter)使用`--windowed`。 ### 高级:添加版本信息和数字签名 #### 版本信息 创建一个版本信息文件(如`version_info.txt`): ```txt # UTF-8 # # For more details about fixed file info 'ffi' see: # http://msdn.microsoft.com/en-us/library/ms646997.aspx VSVersionInfo( ffi=FixedFileInfo( # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4) # Set not needed items to zero 0. filevers=(1, 0, 0, 0), prodvers=(1, 0, 0, 0), # Contains a bitmask that specifies the valid bits 'flags'r mask=0x3f, # Contains a bitmask that specifies the Boolean attributes of the file. flags=0x0, # The operating system for which this file was designed. # 0x4 - NT and there is no need to change it. OS=0x4, # The general type of file. # 0x1 - the file is an application. fileType=0x1, # The function of the file. # 0x0 - the function is not defined for this fileType subtype=0x0, # Creation date and time stamp. date=(0, 0) ), kids=[ StringFileInfo( [ StringTable( '040904B0', [StringStruct('CompanyName', 'YourCompany'), StringStruct('FileDescription', 'Your Description'), StringStruct('FileVersion', '1.0.0'), StringStruct('InternalName', 'YourScript'), StringStruct('LegalCopyright', 'Copyright (c) 2024 YourCompany'), StringStruct('OriginalFilename', 'YourScript.exe'), StringStruct('ProductName', 'Your Product'), StringStruct('ProductVersion', '1.0.0')]) ]), VarFileInfo([VarStruct('Translation', [0, 1200])]) ] ) ``` 然后在打包命令中添加: ```python cmd.append("--version-file=version_info.txt") ``` #### 数字签名 打包后,使用签名工具(如SignTool)进行签名: ```bash signtool sign /f mycert.pfx /p password /t http://timestamp.digicert.com dist/your_script.exe ``` ### 结论 通过以上步骤,我们可以将Python脚本打包成一个独立的exe文件,并且支持所有Windows环境。 §§相关问题§§: 1. 如何为打包的EXE文件添加版本信息和图标? 2. 打包后程序运行出现“Failed to execute script”错误如何调试? 3. 如何减小PyInstaller打包后生成的可执行文件大小? 4. 如何打包一个包含多个Python脚本和复杂依赖的项目? </think> # 将Python文件转换为支持所有环境的EXE文件 下面我将详细介绍如何将Python脚本转换为独立的EXE文件,确保在所有Windows环境中都能运行,无需安装Python或其他依赖。 ## 完整打包解决方案 ```python # build_exe.py - 强大的跨环境打包脚本 import os import sys import shutil import subprocess import platform import glob from pathlib import Path import tempfile import zipfile import urllib.request def is_admin(): """检查是否以管理员权限运行""" try: return ctypes.windll.shell32.IsUserAnAdmin() != 0 except: return False def run_as_admin(): """以管理员权限重新运行脚本""" script = os.path.abspath(sys.argv[0]) params = ' '.join([script] + sys.argv[1:]) ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, params, None, 1) sys.exit(0) def install_pyinstaller(): """确保PyInstaller已安装""" try: import pyinstaller print(f"PyInstaller版本: {pyinstaller.__version__}") except ImportError: print("正在安装PyInstaller...") subprocess.check_call([sys.executable, "-m", "pip", "install", "pyinstaller", "--upgrade"]) print("PyInstaller安装完成") def create_default_icon(): """创建默认应用图标""" icon_path = Path("app_icon.ico") if not icon_path.exists(): print("创建默认应用图标...") # 使用PIL创建简单图标 try: from PIL import Image, ImageDraw img = Image.new('RGBA', (256, 256), (30, 144, 255)) # 道奇蓝背景 draw = ImageDraw.Draw(img) draw.ellipse([(50, 50), (206, 206)], fill=(255, 255, 255)) # 白色圆形 img.save("app_icon.ico", sizes=[(256, 256)]) print("默认图标创建成功") except ImportError: # 如果PIL不可用,下载默认图标 print("下载默认图标...") icon_url = "https://raw.githubusercontent.com/python-exe/basic-icons/main/default.ico" urllib.request.urlretrieve(icon_url, "app_icon.ico") print("默认图标下载完成") return icon_path def create_spec_file(script_name): """创建自定义的.spec文件""" script_stem = Path(script_name).stem spec_content = f"""# -*- mode: python ; coding: utf-8 -*- block_cipher = None a = Analysis( ['{script_name}'], pathex=[], binaries=[], datas=[], hiddenimports=[], hookspath=[], hooksconfig={{}}, runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False, ) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE( pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='{script_stem}', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console={'False' if is_gui_script(script_name) else 'True'}, disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, icon='app_icon.ico', version_file='version_info.txt' if os.path.exists('version_info.txt') else None, ) """ spec_path = f"{script_stem}.spec" with open(spec_path, "w", encoding="utf-8") as f: f.write(spec_content) print(f"已创建spec文件: {spec_path}") return spec_path def is_gui_script(script_path): """检测是否为GUI脚本""" gui_keywords = ["tkinter", "PyQt", "PySide", "wx", "Kivy", "pygame"] try: with open(script_path, "r", encoding="utf-8") as f: content = f.read().lower() return any(keyword in content for keyword in gui_keywords) except: return False def collect_dependencies(): """收集依赖项和资源文件""" print("收集依赖项...") deps = [] # 添加data目录中的所有文件 if Path("data").exists(): for item in Path("data").rglob("*"): if item.is_file(): rel_path = os.path.relpath(item, "data") deps.append(f"--add-data={str(item)};data/{os.path.dirname(rel_path)}") # 添加images目录中的图片 if Path("images").exists(): deps.append(f"--add-data=images;images") # 添加配置文件 if Path("config").exists(): deps.append(f"--add-data=config;config") # 添加常见的隐藏导入 common_hidden_imports = [ "pkg_resources.py2_warn", "numpy", "pandas", "scipy", "sklearn", "PyQt5.Qt", "PyQt5.sip", "tkinter" ] for imp in common_hidden_imports: deps.append(f"--hidden-import={imp}") return deps def build_exe(script_name): """使用PyInstaller构建EXE文件""" script_stem = Path(script_name).stem spec_path = f"{script_stem}.spec" # 确保spec文件存在 if not Path(spec_path).exists(): spec_path = create_spec_file(script_name) # 构建命令 cmd = [ sys.executable, "-m", "PyInstaller", spec_path, "--noconfirm", "--clean", "--onefile", "--distpath", "dist", "--workpath", "build", *collect_dependencies(), "--upx-dir", "upx" if Path("upx").exists() else "", ] # 移除空参数 cmd = [arg for arg in cmd if arg] print(f"构建命令: {' '.join(cmd)}") try: # 创建构建环境 env = os.environ.copy() env["PYTHONOPTIMIZE"] = "1" # 启用优化 # 执行构建 result = subprocess.run(cmd, check=True, env=env) if result.returncode == 0: exe_path = Path("dist") / f"{script_stem}.exe" if exe_path.exists(): print(f"\n构建成功!EXE文件位于: {exe_path}") return True return False except subprocess.CalledProcessError as e: print(f"\n构建失败: {e}") return False def create_version_info(): """创建版本信息文件""" version_path = "version_info.txt" if not Path(version_path).exists(): print("创建默认版本信息...") content = """# UTF-8 # VSVersionInfo( ffi=FixedFileInfo( filevers=(1, 0, 0, 0), prodvers=(1, 0, 0, 0), mask=0x3f, flags=0x0, OS=0x40004, fileType=0x1, subtype=0x0, date=(0, 0) ), kids=[ StringFileInfo( [ StringTable( '040904B0', [StringStruct('CompanyName', 'Your Company'), StringStruct('FileDescription', 'Your Application'), StringStruct('FileVersion', '1.0.0'), StringStruct('InternalName', 'YourApp'), StringStruct('LegalCopyright', 'Copyright © 2023'), StringStruct('OriginalFilename', 'YourApp.exe'), StringStruct('ProductName', 'Your Application'), StringStruct('ProductVersion', '1.0.0')]) ]), VarFileInfo([VarStruct('Translation', [0x409, 1200])]) ] ) """ with open(version_path, "w", encoding="utf-8") as f: f.write(content) return version_path def download_vc_redist(): """下载VC++运行库""" vc_redist_path = Path("vcredist_x64.exe") if not vc_redist_path.exists(): print("下载Visual C++运行库...") vc_redist_url = "https://aka.ms/vs/17/release/vc_redist.x64.exe" try: urllib.request.urlretrieve(vc_redist_url, "vcredist_x64.exe") print("VC++运行库下载完成") except Exception as e: print(f"下载VC++运行库失败: {e}") return vc_redist_path if vc_redist_path.exists() else None def create_installer(script_name): """创建安装包""" script_stem = Path(script_name).stem exe_path = Path("dist") / f"{script_stem}.exe" if not exe_path.exists(): print("错误: EXE文件不存在") return # 创建安装脚本 install_content = f"""@echo off echo 正在安装 {script_stem}... :: 检查管理员权限 net session >nul 2>&1 if %errorLevel% neq 0 ( echo 请以管理员权限运行此安装程序 pause exit /b 1 ) :: 安装VC运行库(如果不存在) if not exist "%SystemRoot%\\System32\\vcruntime140.dll" ( echo 正在安装Visual C++ 2015-2022运行库... start /wait vcredist_x64.exe /install /quiet /norestart ) :: 创建程序目录 set program_dir="%ProgramFiles%\\{script_stem}" if not exist %program_dir% ( mkdir %program_dir% ) :: 复制文件 copy "{exe_path.name}" %program_dir%\\{script_stem}.exe :: 创建快捷方式 set shortcut="%ProgramData%\\Microsoft\\Windows\\Start Menu\\Programs\\{script_stem}.lnk" set target="%program_dir%\\{script_stem}.exe" set ws=WScript.CreateObject("WScript.Shell") set sc=ws.CreateShortcut(%shortcut%) sc.TargetPath=%target% sc.Save echo 安装完成!您可以在开始菜单中找到 {script_stem} pause """ # 保存安装脚本 install_script = Path("dist") / "install.bat" with open(install_script, "w") as f: f.write(install_content) # 下载VC++运行库 vc_redist = download_vc_redist() if vc_redist: shutil.copy(vc_redist, "dist") # 创建ZIP包 zip_path = f"{script_stem}_installer.zip" with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf: zipf.write(exe_path, arcname=exe_path.name) zipf.write(install_script, arcname="install.bat") if vc_redist: zipf.write(vc_redist, arcname="vcredist_x64.exe") print(f"\n已创建安装包: {zip_path}") def main(): print("===== PythonEXE高级打包工具 =====") # 检查管理员权限 if not is_admin(): print("\n需要管理员权限继续执行") run_as_admin() # 获取要打包的脚本 if len(sys.argv) < 2: print("用法: python build_exe.py <script.py>") return script_name = sys.argv[1] # 验证脚本存在 if not Path(script_name).exists(): print(f"错误: 文件 {script_name} 不存在") return # 安装必要组件 install_pyinstaller() # 准备环境 create_default_icon() create_version_info() # 构建EXE if build_exe(script_name): # 创建安装包 create_installer(script_name) print("\n打包完成!程序可在所有Windows环境中运行") else: print("\n打包失败,请检查错误信息") if __name__ == "__main__": main() ``` ## 打包过程详解 ### 1. 准备工作 - **管理员权限检查**:确保有足够权限执行所有操作 - **PyInstaller安装**:自动安装最新版打包工具 - **图标创建**:生成默认应用图标或下载备用图标 - **版本信息**:自动创建版本资源文件 ### 2. 智能构建 - **自动检测GUI应用**:根据脚本内容判断是否需要控制台窗口 - **依赖收集**:自动扫描并包含常见资源文件(data, images, config) - **隐藏导入处理**:自动添加常见模块的隐藏导入(numpy, pandas等) - **UPX压缩**:使用UPX压缩可执行文件减小体积 ### 3. 运行时保证 - **VC++运行库**:自动下载并包含Visual C++ Redistributable - **安装脚本**:创建一键安装批处理文件 - **管理员权限**:安装时自动请求管理员权限 - **开始菜单快捷方式**:自动创建程序快捷方式 ### 4. 输出结果 1. 生成的EXE文件在`dist`目录 2. 完整的安装包ZIP文件包含: - EXE程序 - 安装脚本 - VC++运行库 ## 使用说明 1. 保存上述代码为`build_exe.py` 2. 将要打包的Python脚本放在同一目录 3. 运行打包命令: ``` python build_exe.py your_script.py ``` 4. 在`dist`目录获取生成的`your_script_installer.zip` ## 确保跨环境兼容性的关键技术 ### 1. 运行时依赖处理 ```python # 自动下载VC++运行库 def download_vc_redist(): vc_redist_url = "https://aka.ms/vs/17/release/vc_redist.x64.exe" urllib.request.urlretrieve(vc_redist_url, "vcredist_x64.exe") ``` ### 2. 路径兼容性 ```python # 在代码中正确处理资源路径 def resource_path(relative_path): """获取资源的绝对路径""" try: base_path = sys._MEIPASS # PyInstaller创建的临时文件夹 except AttributeError: base_path = os.path.abspath(".") return os.path.join(base_path, relative_path) # 使用示例 image_path = resource_path("images/logo.png") ``` ### 3. 自动依赖检测 ```python def is_gui_script(script_path): """检测是否为GUI脚本""" gui_keywords = ["tkinter", "PyQt", "PySide", "wx", "Kivy", "pygame"] with open(script_path, "r") as f: content = f.read().lower() return any(keyword in content for keyword in gui_keywords) ``` ### 4. 文件包含策略 ```python def collect_dependencies(): """自动收集资源文件""" deps = [] if Path("data").exists(): deps.append("--add-data=data;data") if Path("images").exists(): deps.append("--add-data=images;images") return deps ``` ## 高级打包技巧 ### 1. 减小EXE体积 - 使用UPX压缩:添加`--upx-dir=upx`参数 - 排除不必要的模块: ```python cmd.append("--exclude-module=unittest") cmd.append("--exclude-module=test") ``` - 使用虚拟环境:只安装必要的依赖 ### 2. 添加数字签名 ```python def sign_exe(exe_path): """为EXE文件添加数字签名""" if not Path("sign_tool.bat").exists(): return cmd = [ "sign_tool.bat", str(exe_path) ] subprocess.run(cmd) ``` 签名脚本示例(`sign_tool.bat`): ```batch @echo off set CERT_FILE=my_cert.pfx set CERT_PASSWORD=my_password set TIMESTAMP_URL=http://timestamp.digicert.com signtool sign /f "%CERT_FILE%" /p "%CERT_PASSWORD%" /t "%TIMESTAMP_URL%" %1 ``` ### 3. 创建专业安装程序 使用Inno Setup创建专业安装程序: 1. 安装Inno Setup:http://www.jrsoftware.org/isdl.php 2. 创建安装脚本(`setup.iss`): ```iss [Setup] AppName=MyApp AppVersion=1.0 DefaultDirName={pf}\MyApp OutputDir=.\dist OutputBaseFilename=MyApp_Setup SetupIconFile=.\app_icon.ico Compression=lzma2 SolidCompression=yes [Files] Source: ".\dist\MyApp.exe"; DestDir: "{app}" Source: ".\vcredist_x64.exe"; DestDir: "{tmp}" [Run] Filename: "{tmp}\vcredist_x64.exe"; Parameters: "/install /quiet /norestart"; StatusMsg: "Installing VC++ Redistributable..." [Icons] Name: "{group}\MyApp"; Filename: "{app}\MyApp.exe" ``` 3. 编译安装程序: ``` iscc setup.iss ``` ## 跨环境测试建议 1. **虚拟机测试**:在以下Windows版本测试: - Windows 7 SP1 - Windows 10 (不同版本) - Windows 11 - Windows Server 2016/2019 2. **兼容性设置**:在EXE属性中设置: - 以兼容模式运行 - 以管理员身份运行 3. **依赖检查**:使用Dependency Walker检查缺少的DLL: http://www.dependencywalker.com/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值