#!/usr/bin/env python3 """ Сборка ФИАС_поиск.exe — standalone, без установки Python. Запускать на Windows с 32-bit Python 3.8: python build.py Перед первым запуском установить зависимости: pip install -r requirements.txt """ from __future__ import annotations import subprocess import sys import shutil import struct import platform from pathlib import Path ROOT = Path(__file__).parent def check_env(): bits = struct.calcsize("P") * 8 ver = sys.version_info print(f"Python {ver.major}.{ver.minor}.{ver.micro} {bits}-bit {platform.system()}") if ver < (3, 8): sys.exit("Требуется Python 3.8+") if bits != 32: print(f"ВНИМАНИЕ: Python {bits}-bit. Для win32 .exe используйте 32-bit Python.") try: import PyInstaller print(f"PyInstaller {PyInstaller.__version__}") except ImportError: print("Установка PyInstaller...") subprocess.run( [sys.executable, "-m", "pip", "install", "pyinstaller>=5.13,<7"], check=True, ) def clean(): for name in ("build", "dist", "__pycache__"): p = ROOT / name if p.exists(): shutil.rmtree(p) for spec in ROOT.glob("*.spec"): spec.unlink() print("Очищено") def build(): cmd = [ sys.executable, "-m", "PyInstaller", "--onefile", "--noconsole", "--name", "ФИАС_поиск", # Собрать целиком вместе с data-файлами "--collect-all", "selenium", "--collect-all", "webdriver_manager", "--collect-all", "pdfplumber", "--collect-all", "pdfminer", "--collect-all", "openpyxl", "--collect-all", "certifi", # Явные скрытые импорты "--hidden-import", "selenium.webdriver.firefox.webdriver", "--hidden-import", "selenium.webdriver.firefox.options", "--hidden-import", "selenium.webdriver.firefox.service", "--hidden-import", "selenium.webdriver.support.expected_conditions", "--hidden-import", "selenium.webdriver.common.by", "--hidden-import", "webdriver_manager.firefox", "--hidden-import", "pdfminer.high_level", "--hidden-import", "pdfminer.converter", "--hidden-import", "pdfminer.layout", "--hidden-import", "pdfminer.pdfpage", "--hidden-import", "pdfminer.pdfinterp", "--hidden-import", "pdfminer.pdffont", "--hidden-import", "pdfminer.pdftypes", "--hidden-import", "pdfminer.pdfparser", "--hidden-import", "pdfminer.pdfdevice", "--hidden-import", "openpyxl.styles", "--hidden-import", "openpyxl.utils", "--hidden-import", "cryptography", "--hidden-import", "tkinter", "--hidden-import", "tkinter.filedialog", "--hidden-import", "tkinter.scrolledtext", "--hidden-import", "tkinter.messagebox", "--hidden-import", "queue", "--hidden-import", "logging", "--hidden-import", "configparser", "--hidden-import", "platform", str(ROOT / "main.py"), ] print("\nСборка...") result = subprocess.run(cmd, cwd=ROOT) if result.returncode != 0: sys.exit("PyInstaller завершился с ошибкой") exe = ROOT / "dist" / "ФИАС_поиск.exe" if exe.exists(): mb = exe.stat().st_size / 1024 / 1024 print(f"\n{'='*55}") print(f" Готово: {exe}") print(f" Размер: {mb:.1f} МБ") print(f"{'='*55}") print(" Firefox должен быть установлен на компьютере.") print(" geckodriver скачается автоматически при первом запуске.") else: sys.exit("dist/ФИАС_поиск.exe не найден после сборки") if __name__ == "__main__": import argparse p = argparse.ArgumentParser() p.add_argument("--clean", action="store_true", help="Только очистить build/dist") args = p.parse_args() if args.clean: clean() else: check_env() clean() build()