【Python】 基于纯 C 语言的项目启动器
·
pylaunch 是一个基于嵌入式 Python(Embedded Python)的 Windows 启动器,允许开发者将 Python 项目与运行时一起打包并分发,从而无需在目标系统上安装 Python 环境。本教程将介绍 pylaunch 的原理、使用方法和打包方式。
项目特点
- 独立启动器:通过纯 C 语言编写,默认不显示命令行窗口,可通过参数配置启用无窗口模式。
- 嵌入式 Python 支持:自动加载本地目录中的
python3.dll(来自官方嵌入式 Python 发行版)。 - 环境隔离:通过设置环境变量和动态路径,构建项目的私有运行环境。
- 主脚本识别:自动查找并运行与可执行文件的同名模块,与 Python 脚本解耦。
- 自动路径配置:动态将
packages和source目录添加到sys.path。
项目结构
your_project/
├── source/
│ └── pylaunch.py # 与 exe 同名模块
├── packages/ # 可选:项目依赖(纯 Python 库)
├── runtime/ # 嵌入式 Python 运行时(解压官方 zip 包)
│ ├── python3.dll
│ └── ...
└── pylaunch.exe # 编译好的 C 启动器
C 语言程序源码
#include <stdlib.h>
#include <wchar.h>
#include <windows.h>
// 主函数:启动 Python 运行时
int wmain() {
int argc;
LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc);
if (!argv)
return 1;
// 获取可执行路径
wchar_t exePath[MAX_PATH];
if (!GetModuleFileNameW(NULL, exePath, MAX_PATH)) {
LocalFree(argv);
return 1;
}
// 构建 Python 初始化脚本
wchar_t initScript[4096];
_snwprintf(initScript, 4096,
L"import sys,os,runpy\n"
L"exe_path=r'%s'\n"
L"home=os.path.dirname(exe_path)\n"
L"sys.path[0:0]=[os.path.join(home,'source'),os.path.join(home,'"
L"packages')]\n"
L"module_name=os.path.splitext(os.path.basename(exe_path))[0]\n"
L"sys.argv=[module_name]+sys.argv[1:]\n"
L"runpy.run_module(module_name,run_name='__main__')\n",
exePath);
// 构造 Py_Main 参数
int pyArgc = argc + 5;
wchar_t **pyArgv = malloc(sizeof(wchar_t *) * pyArgc);
if (!pyArgv) {
LocalFree(argv);
return 1;
}
pyArgv[0] = argv[0];
pyArgv[1] = L"-I";
pyArgv[2] = L"-s";
pyArgv[3] = L"-S";
pyArgv[4] = L"-c";
pyArgv[5] = initScript;
for (int i = 1; i < argc; ++i)
pyArgv[5 + i] = argv[i];
// 设置 DLL 目录
wchar_t runtimeDir[MAX_PATH], pythonDll[MAX_PATH];
wcsncpy(runtimeDir, exePath, MAX_PATH);
wchar_t *lastSlash = wcsrchr(runtimeDir, L'\\');
if (lastSlash)
*lastSlash = 0;
wcscat(runtimeDir, L"\\runtime");
SetDllDirectoryW(runtimeDir);
wcscpy(pythonDll, runtimeDir);
wcscat(pythonDll, L"\\python3.dll");
// 加载 Python DLL
HMODULE hDLL = LoadLibraryW(pythonDll);
if (!hDLL) {
free(pyArgv);
LocalFree(argv);
return 1;
}
// 调用 Py_Main
int (*Py_Main)(int, wchar_t **) = (void *)GetProcAddress(hDLL, "Py_Main");
if (!Py_Main) {
FreeLibrary(hDLL);
free(pyArgv);
LocalFree(argv);
return 1;
}
int ret = Py_Main(pyArgc, pyArgv);
FreeLibrary(hDLL);
free(pyArgv);
LocalFree(argv);
return ret;
}
编译和构建
使用 MinGW 编译 C 启动器
gcc pylaunch.c -o pylaunch.exe -municode -static-libgcc -Os -s -flto -fno-exceptions
支持无窗口模式(可选)
gcc pylaunch.c -o pylaunch.exe -municode -mwindows -static-libgcc -Os -s -flto -fno-exceptions
添加应用图标
- 创建资源文件
pylaunch.rc:
IDI_ICON1 ICON "icon.ico"
- 编译资源文件为
.o:
windres pylaunch.rc -o pylaunch_res.o
- 编译最终可执行文件并链接资源:
gcc pylaunch.c pylaunch_res.o -o pylaunch.exe -municode -static-libgcc -Os -s -flto -fno-exceptions
嵌入式 Python 运行时
获取 Python 运行时
从 Python 官网 下载嵌入式 Python 包(embeddable package)。
配置 runtime/ 目录
解压缩下载的文件到 runtime/ 目录:
your_project/
└── runtime/
├── python3.dll
├── python312.zip
├── _asyncio.pyd
└── ...
可选优化
- 删除不需要的
.pyd文件和.exe文件。 - 保留最小运行子集(如
.dll、.zip和部分.pyd)。
总结
通过 pylaunch 启动器,你可以轻松将 Python 项目打包为独立的 Windows 应用程序,无需在目标机器上安装 Python 环境。只需要一个可执行文件,你的 Python 脚本即可在没有 Python 安装的环境中运行,极大地简化了项目的分发与部署流程。
更多推荐


所有评论(0)