查找可执行文件(跨平台)
(self)
| 300 | self.process.kill() |
| 301 | |
| 302 | def _find_executable(self): |
| 303 | """查找可执行文件(跨平台)""" |
| 304 | # 程序所在目录(支持双击运行) |
| 305 | app_dir = get_app_dir() |
| 306 | # 当前工作目录 |
| 307 | current_dir = Path.cwd() |
| 308 | |
| 309 | # Windows 和 Unix 的可执行文件扩展名 |
| 310 | exe_ext = '.exe' if sys.platform == 'win32' else '' |
| 311 | |
| 312 | # 可能的可执行文件路径(按优先级) |
| 313 | possible_paths = [ |
| 314 | app_dir / f'ech-workers{exe_ext}', |
| 315 | current_dir / f'ech-workers{exe_ext}', |
| 316 | # Windows 特定路径 |
| 317 | app_dir / 'ech-workers.exe' if sys.platform == 'win32' else None, |
| 318 | current_dir / 'ech-workers.exe' if sys.platform == 'win32' else None, |
| 319 | # Unix 路径(无扩展名) |
| 320 | app_dir / 'ech-workers' if sys.platform != 'win32' else None, |
| 321 | current_dir / 'ech-workers' if sys.platform != 'win32' else None, |
| 322 | ] |
| 323 | |
| 324 | # 过滤掉 None 值 |
| 325 | possible_paths = [p for p in possible_paths if p is not None] |
| 326 | |
| 327 | for path in possible_paths: |
| 328 | if path.exists(): |
| 329 | # Windows: 检查文件是否存在即可(.exe 文件) |
| 330 | # Unix: 检查文件权限 |
| 331 | if sys.platform == 'win32': |
| 332 | # Windows 上,.exe 文件可以直接运行 |
| 333 | if path.suffix.lower() == '.exe': |
| 334 | return str(path) |
| 335 | # 或者检查文件是否可执行 |
| 336 | try: |
| 337 | with open(path, 'rb') as f: |
| 338 | header = f.read(2) |
| 339 | # PE 文件头 |
| 340 | if header == b'MZ': |
| 341 | return str(path) |
| 342 | except: |
| 343 | pass |
| 344 | else: |
| 345 | # Unix/Linux/macOS: 检查执行权限 |
| 346 | if os.access(path, os.X_OK): |
| 347 | return str(path) |
| 348 | # 或者检查是否是二进制文件 |
| 349 | try: |
| 350 | with open(path, 'rb') as f: |
| 351 | header = f.read(4) |
| 352 | # ELF 或 Mach-O |
| 353 | if (header.startswith(b'\x7fELF') or |
| 354 | header.startswith(b'\xfe\xed\xfa') or |
| 355 | header.startswith(b'#!')): |
| 356 | # 尝试添加执行权限 |
| 357 | try: |
| 358 | os.chmod(path, 0o755) |
| 359 | except: |