package_project.py

#!/usr/bin/env python3
"""
AI Quant 项目打包脚本
用于生成可直接部署的完整代码包+全配套文档
"""

import sys
import os
import logging
import zipfile
import shutil
from datetime import datetime

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    handlers=[
        logging.StreamHandler()
    ]
)

logger = logging.getLogger("AIQuant.package")


def main():
    """
    主入口函数
    """
    logger.info("AI Quant 项目打包开始")

    try:
        # 获取项目根目录
        project_root = os.path.dirname(
            os.path.dirname(os.path.abspath(__file__)))
        logger.info(f"项目根目录: {project_root}")

        # 生成打包文件名
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        package_name = f"AIQuant_{timestamp}"
        package_dir = os.path.join(project_root, "..", package_name)
        package_zip = f"{package_name}.zip"

        logger.info(f"打包文件名: {package_zip}")

        # 创建临时打包目录
        os.makedirs(package_dir, exist_ok=True)
        logger.info(f"临时打包目录: {package_dir}")

        # 复制项目文件到临时打包目录
        logger.info("复制项目文件到临时打包目录...")

        # 需要复制的目录
        directories_to_copy = [
            "core",
            "service",
            "app",
            "config",
            "script"
        ]

        for directory in directories_to_copy:
            src_dir = os.path.join(project_root, directory)
            dst_dir = os.path.join(package_dir, directory)

            if os.path.exists(src_dir):
                shutil.copytree(src_dir, dst_dir)
                logger.info(f"复制目录: {src_dir} -> {dst_dir}")
            else:
                logger.warning(f"目录不存在: {src_dir}")

        # 需要复制的文件
        files_to_copy = [
            "README.md",
            "requirements.txt",
            "__init__.py"
        ]

        for file in files_to_copy:
            src_file = os.path.join(project_root, file)
            dst_file = os.path.join(package_dir, file)

            if os.path.exists(src_file):
                shutil.copy(src_file, dst_file)
                logger.info(f"复制文件: {src_file} -> {dst_file}")
            else:
                logger.warning(f"文件不存在: {src_file}")

        # 打包项目
        logger.info("开始打包项目...")
        with zipfile.ZipFile(package_zip, 'w', zipfile.ZIP_DEFLATED) as zipf:
            for root, _, files in os.walk(package_dir):
                for file in files:
                    file_path = os.path.join(root, file)
                    arcname = os.path.relpath(file_path, package_dir)
                    zipf.write(file_path, arcname)
                    logger.debug(f"添加文件到包: {file_path}")

        logger.info(f"打包成功: {package_zip}")

        # 清理临时目录
        logger.info("清理临时打包目录...")
        shutil.rmtree(package_dir)
        logger.info("临时打包目录清理完成")

        # 验证打包是否成功
        if os.path.exists(package_zip):
            logger.info(f"打包文件大小: {os.path.getsize(package_zip)} 字节")
            logger.info("项目打包完成")
            return True
        else:
            logger.error("打包文件不存在")
            return False
    except Exception as e:
        logger.error(f"打包过程中出错: {e}")
        logger.exception("详细错误信息:")
        return False


if __name__ == "__main__":
    try:
        success = main()
        sys.exit(0 if success else 1)
    except KeyboardInterrupt:
        logger.info("程序被用户中断")
        sys.exit(0)