haha
This commit is contained in:
@@ -1,21 +1,41 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
# 客户端 GUI 打包配置
|
||||
# 用法: 在项目根目录执行 pyinstaller build_client.spec
|
||||
# 用法: 在项目根目录 (boss_dp) 执行: pyinstaller build_client.spec
|
||||
|
||||
import os
|
||||
_project_root = os.path.dirname(os.path.abspath(SPECPATH))
|
||||
_spec_dir = os.path.dirname(os.path.abspath(SPECPATH))
|
||||
_run_client = os.path.join(_spec_dir, 'run_client.py')
|
||||
if not os.path.isfile(_run_client):
|
||||
_spec_dir = os.getcwd()
|
||||
_run_client = os.path.join(_spec_dir, 'run_client.py')
|
||||
|
||||
block_cipher = None
|
||||
|
||||
a = Analysis(
|
||||
[os.path.join(_project_root, 'run_client.py')],
|
||||
pathex=[_project_root],
|
||||
[_run_client],
|
||||
pathex=[_spec_dir],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=[
|
||||
'client_gui',
|
||||
'client_gui.main',
|
||||
'client_gui.config_store',
|
||||
'worker',
|
||||
'worker.main',
|
||||
'worker.ws_client',
|
||||
'worker.bit_browser',
|
||||
'worker.browser_control',
|
||||
'worker.config',
|
||||
'worker.tasks',
|
||||
'worker.tasks.registry',
|
||||
'worker.tasks.base',
|
||||
'worker.tasks.boss_recruit',
|
||||
'worker.tasks.check_login',
|
||||
'tunnel',
|
||||
'tunnel.client',
|
||||
'tunnel.protocol',
|
||||
'common',
|
||||
'common.protocol',
|
||||
'PyQt5',
|
||||
'PyQt5.QtCore',
|
||||
'PyQt5.QtWidgets',
|
||||
|
||||
@@ -72,21 +72,23 @@ def _is_frozen() -> bool:
|
||||
return getattr(sys, "frozen", False)
|
||||
|
||||
|
||||
def _get_worker_launcher() -> tuple[str, str]:
|
||||
def _get_worker_launcher() -> tuple[str, str, bool]:
|
||||
"""返回 (可执行路径, 工作目录, 是否用 --worker 模式)。"""
|
||||
if _is_frozen():
|
||||
exe_dir = os.path.dirname(sys.executable)
|
||||
worker_exe = os.path.join(exe_dir, "worker.exe")
|
||||
if os.path.isfile(worker_exe):
|
||||
return worker_exe, exe_dir
|
||||
return sys.executable, exe_dir, True
|
||||
project_root = get_project_root()
|
||||
return sys.executable, project_root
|
||||
return sys.executable, project_root, False
|
||||
|
||||
|
||||
def run_worker(server_url: str, worker_id: str, worker_name: str, log_callback) -> subprocess.Popen | None:
|
||||
"""启动 Worker 子进程。"""
|
||||
launcher, cwd = _get_worker_launcher()
|
||||
is_python = launcher == sys.executable
|
||||
if is_python:
|
||||
"""启动 Worker 子进程(同一 exe 的 --worker 模式或 python -m worker.main)。"""
|
||||
launcher, cwd, use_worker_flag = _get_worker_launcher()
|
||||
if use_worker_flag:
|
||||
cmd = [launcher, "--worker", "--server", server_url, "--worker-id", worker_id, "--worker-name", worker_name]
|
||||
env = os.environ
|
||||
encoding = "gbk" if sys.platform == "win32" else "utf-8"
|
||||
else:
|
||||
cmd = [
|
||||
launcher, "-m", "worker.main",
|
||||
"--server", server_url,
|
||||
@@ -95,11 +97,6 @@ def run_worker(server_url: str, worker_id: str, worker_name: str, log_callback)
|
||||
]
|
||||
env = {**os.environ, "PYTHONIOENCODING": "utf-8"}
|
||||
encoding = "utf-8"
|
||||
else:
|
||||
cmd = [launcher, "--server", server_url, "--worker-id", worker_id, "--worker-name", worker_name]
|
||||
env = os.environ
|
||||
# worker.exe 在 Windows 上可能用 GBK 输出
|
||||
encoding = "gbk" if sys.platform == "win32" else "utf-8"
|
||||
try:
|
||||
return subprocess.Popen(
|
||||
cmd, cwd=cwd, env=env,
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
客户端 GUI 启动入口。
|
||||
使用方式: python run_client.py
|
||||
客户端统一入口:根据参数决定启动 GUI 或 Worker 模式。
|
||||
- 无参数 / 正常启动 → GUI 界面
|
||||
- 带 --worker 参数 → Worker 模式(由 GUI 点击「启动」时调用)
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from client_gui.main import main
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
if "--worker" in sys.argv:
|
||||
from worker.main import main as worker_main
|
||||
worker_main()
|
||||
else:
|
||||
from client_gui.main import main as gui_main
|
||||
gui_main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -25,6 +25,7 @@ logger = logging.getLogger("worker.main")
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description="Browser Control Worker Agent")
|
||||
parser.add_argument("--worker", action="store_true", help=argparse.SUPPRESS)
|
||||
parser.add_argument(
|
||||
"--server",
|
||||
default=config.SERVER_WS_URL,
|
||||
|
||||
14
部署说明.md
14
部署说明.md
@@ -25,18 +25,8 @@ python app.py
|
||||
### 方式 B:打包为 exe(推荐,无需 Python)
|
||||
|
||||
1. 安装 PyInstaller:`pip install pyinstaller`
|
||||
2. 在项目根目录执行打包:
|
||||
```bash
|
||||
# 打包客户端 GUI
|
||||
pyinstaller build_client.spec
|
||||
|
||||
# 打包 Worker(供 GUI 的「启动」按钮调用)
|
||||
pyinstaller build_worker.spec
|
||||
```
|
||||
3. 将生成的文件合并:
|
||||
- `dist/BOSS直聘Worker客户端/` 为 GUI 输出目录
|
||||
- 将 `dist/worker/worker.exe` 复制到 `dist/BOSS直聘Worker客户端/` 目录内
|
||||
4. 将整个 `BOSS直聘Worker客户端` 文件夹发给客户,客户双击 `BOSS直聘Worker客户端.exe` 即可使用
|
||||
2. 在项目根目录执行打包:`pyinstaller build_client.spec`
|
||||
3. 将 `dist/BOSS直聘Worker客户端/` 文件夹发给客户,客户双击 `BOSS直聘Worker客户端.exe` 即可使用(GUI 与 Worker 已合并为同一程序,无需 worker.exe)
|
||||
|
||||
### GUI 功能说明
|
||||
|
||||
|
||||
Reference in New Issue
Block a user