From cfe3f1841606eb06953f71ebcf46211d4564a8e0 Mon Sep 17 00:00:00 2001 From: xieyuen <107105640+xieyuen@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:24:44 +0800 Subject: [PATCH 1/9] Add main function and entry point to main.py --- src/program/main.py | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/program/main.py diff --git a/src/program/main.py b/src/program/main.py new file mode 100644 index 0000000..3339ef2 --- /dev/null +++ b/src/program/main.py @@ -0,0 +1,5 @@ +def main(): + pass + +if __name__ == "__main__": + main() From bcc66ee9a2174295bfa23e64e9fc0c7b557aeb19 Mon Sep 17 00:00:00 2001 From: xieyuen <107105640+xieyuen@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:25:43 +0800 Subject: [PATCH 2/9] Change project name and remove build system Updated project name and removed build system section. --- pyproject.toml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 12ecbb1..ad3eaa9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,5 @@ -[build-system] -requires = ["uv_build >= 0.9.2, <0.10.0"] -build-backend = "uv_build" - [project] -name = "math-modeling-template" +name = "program" version = "0.1.0" description = "Add your descriptions here" dependencies = [ From 8a924e2ba516b494240f1a941118c9130ff86e84 Mon Sep 17 00:00:00 2001 From: xieyuen <107105640+xieyuen@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:26:38 +0800 Subject: [PATCH 3/9] Add GitHub Actions workflow to run program --- .github/run_program | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/run_program diff --git a/.github/run_program b/.github/run_program new file mode 100644 index 0000000..43799b5 --- /dev/null +++ b/.github/run_program @@ -0,0 +1,46 @@ +name: Run Program + +on: + workflow_dispatch: + push: + paths: + - src/program/** + - pyproject.toml + pull_request: + paths: + - src/program/** + - pyproject.toml + +jobs: + run: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: 3.13 + + - name: Install Dependencies + run: | + python -m pip install --upgrade pip + pip install uv + uv sync + + - name: Run Program + run: | + uv pip install -e . + uv run python src/program/main.py + + - name: Upload Logs + if: always() + uses: actions/upload-artifact@v7 + with: + name: logs + path: logs/ + archive: true + retention-days: 90 + if-no-files-found: ignore From f111424fb27ac94c42290c77ae5d8705b1a65c26 Mon Sep 17 00:00:00 2001 From: xieyuen <107105640+xieyuen@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:28:01 +0800 Subject: [PATCH 4/9] Disable log upload in run_program workflow Comment out the log upload step in the workflow. --- .../{run_program => workflows/run_program.yml} | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) rename .github/{run_program => workflows/run_program.yml} (73%) diff --git a/.github/run_program b/.github/workflows/run_program.yml similarity index 73% rename from .github/run_program rename to .github/workflows/run_program.yml index 43799b5..9adfa1f 100644 --- a/.github/run_program +++ b/.github/workflows/run_program.yml @@ -35,12 +35,12 @@ jobs: uv pip install -e . uv run python src/program/main.py - - name: Upload Logs - if: always() - uses: actions/upload-artifact@v7 - with: - name: logs - path: logs/ - archive: true - retention-days: 90 - if-no-files-found: ignore + # - name: Upload Logs + # if: always() + # uses: actions/upload-artifact@v7 + # with: + # name: logs + # path: logs/ + # archive: true + # retention-days: 90 + # if-no-files-found: ignore From 6895f580a678bdf26b64a290e7baa63941ff8719 Mon Sep 17 00:00:00 2001 From: xieyuen <107105640+xieyuen@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:29:29 +0800 Subject: [PATCH 5/9] Delete src/.gitkeep --- src/.gitkeep | 1 - 1 file changed, 1 deletion(-) delete mode 100644 src/.gitkeep diff --git a/src/.gitkeep b/src/.gitkeep deleted file mode 100644 index 8b13789..0000000 --- a/src/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - From 242ce65b9c9cb98a8e12dcf4785a160c053d9112 Mon Sep 17 00:00:00 2001 From: xieyuen <107105640+xieyuen@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:30:15 +0800 Subject: [PATCH 6/9] Add logger utility with custom formatting and archiving Implement a logging utility with file archiving and custom formatting. --- src/program/utils/logger.py | 142 ++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 src/program/utils/logger.py diff --git a/src/program/utils/logger.py b/src/program/utils/logger.py new file mode 100644 index 0000000..205a7eb --- /dev/null +++ b/src/program/utils/logger.py @@ -0,0 +1,142 @@ +"""Logger, 主要由 DeepSeek 生成""" + +import datetime +import glob +import logging +import os +import zipfile + +import colorlog + + +class _FileFormatter(logging.Formatter): + """自定义文件格式化器,在时间末尾追加毫秒""" + + def formatTime(self, record, datefmt=None): + ct = self.converter(record.created) + if datefmt: + base_time = datetime.datetime(*ct[:6]).strftime(datefmt) + else: + base_time = datetime.datetime(*ct[:6]).strftime("%Y-%m-%d %H:%M:%S") + return f"{base_time}.{int(record.msecs):03d}" + + +def _archive_old_log(log_dir: str, log_filename: str): + """ + 将上一次运行留下的 program.log 压缩为 program-{date}-{times}.zip。 + date 取自日志文件的修改时间,times 为当天序号(自动递增)。 + """ + log_path = os.path.join(log_dir, log_filename) + if not os.path.isfile(log_path): + return + + # 以文件修改时间作为日志产生的日期 + mtime = os.path.getmtime(log_path) + date_str = datetime.datetime.fromtimestamp(mtime).strftime("%Y-%m-%d") + + # 查找同一天已有的压缩包,确定序号 + pattern = os.path.join(log_dir, f"program-{date_str}-*.zip") + existing = glob.glob(pattern) + max_idx = 0 + for path in existing: + name = os.path.splitext(os.path.basename(path))[0] # program-{date}-{idx} + parts = name.split("-") + if len(parts) >= 4 and parts[-1].isdigit(): + idx = int(parts[-1]) + if idx > max_idx: + max_idx = idx + times = max_idx + 1 + + zip_filename = f"program-{date_str}-{times}.zip" + zip_path = os.path.join(log_dir, zip_filename) + + try: + with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf: + zf.write(log_path, arcname=log_filename) + os.remove(log_path) # 压缩成功后删除原文件 + except Exception as e: + print(f"归档旧日志失败: {e}") + + +_configured = False + + +def setup_logging(log_dir: str = "logs", + log_filename: str = "program.log", + console_level: int = logging.INFO, + file_level: int = logging.DEBUG, + ): + """ + 配置全局日志系统(仅首次调用有效)。 + 控制台输出格式:[HH:MM] [ThreadName/LEVEL] [filename]: message + 文件输出格式: [YYYY-MM-DD HH:MM:SS.ms] [ThreadName/LEVEL] [filename(funcName)]: message + """ + global _configured + if _configured: + return + + os.makedirs(log_dir, exist_ok=True) + _archive_old_log(log_dir, log_filename) + + # 根 Logger 设为最低级别,由 Handler 各自控制 + root = logging.getLogger() + root.setLevel(logging.DEBUG) + root.handlers.clear() + + # --- 控制台 Handler(带颜色)--- + console_fmt = colorlog.ColoredFormatter( + "[%(asctime)s] [%(threadName)s/%(log_color)s%(levelname)s%(reset)s] [%(filename)s]: %(message)s", + datefmt="%H:%M", + log_colors={ + "DEBUG": "cyan", + "INFO": "green", + "WARNING": "yellow", + "ERROR": "red", + "CRITICAL": "red,bg_white", + }, + ) + console_handler = logging.StreamHandler() + console_handler.setLevel(console_level) + console_handler.setFormatter(console_fmt) + root.addHandler(console_handler) + + # --- 文件 Handler(带毫秒)--- + file_fmt = _FileFormatter( + "[%(asctime)s] [%(threadName)s/%(levelname)s] [%(filename)s(%(funcName)s)]: %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + file_handler = logging.FileHandler( + os.path.join(log_dir, log_filename), mode="w", encoding="utf-8", + ) + file_handler.setLevel(file_level) + file_handler.setFormatter(file_fmt) + root.addHandler(file_handler) + + _configured = True + + +def get_logger() -> logging.Logger: + """ + 获取已配置好格式的 Logger。 + 首次调用会自动初始化日志系统(setup_logging)。 + """ + setup_logging() + return logging.getLogger() + + +logger = get_logger() +debug = logger.debug +info = logger.info +warning = logger.warning +error = logger.error +critical = logger.critical +exception = logger.exception + +# # ============ 使用示例 ============ +# if __name__ == "__main__": +# logger = get_logger(__name__) +# logger.debug("这是一条 DEBUG 日志(仅文件)") +# logger.info("HelloWorld") +# logger.warning("警告信息") +# logger.error("错误信息") +# logger.critical("严重错误") From 728b7ffc90ca015742d1807a8f61d008f08fbc14 Mon Sep 17 00:00:00 2001 From: xieyuen <107105640+xieyuen@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:31:04 +0800 Subject: [PATCH 7/9] Add logging to the main function --- src/program/main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/program/main.py b/src/program/main.py index 3339ef2..83f52e5 100644 --- a/src/program/main.py +++ b/src/program/main.py @@ -1,5 +1,7 @@ +from program.utils.logger import logger + def main(): - pass + logger.info("Hello World!") if __name__ == "__main__": main() From c938667ab89de0b01370037e17cfe160f9d7306d Mon Sep 17 00:00:00 2001 From: xieyuen <107105640+xieyuen@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:31:37 +0800 Subject: [PATCH 8/9] Uncomment log upload step in workflow --- .github/workflows/run_program.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/run_program.yml b/.github/workflows/run_program.yml index 9adfa1f..43799b5 100644 --- a/.github/workflows/run_program.yml +++ b/.github/workflows/run_program.yml @@ -35,12 +35,12 @@ jobs: uv pip install -e . uv run python src/program/main.py - # - name: Upload Logs - # if: always() - # uses: actions/upload-artifact@v7 - # with: - # name: logs - # path: logs/ - # archive: true - # retention-days: 90 - # if-no-files-found: ignore + - name: Upload Logs + if: always() + uses: actions/upload-artifact@v7 + with: + name: logs + path: logs/ + archive: true + retention-days: 90 + if-no-files-found: ignore From 7b809663e93456d7ba9c04e96701e51ae03e141f Mon Sep 17 00:00:00 2001 From: xieyuen <107105640+xieyuen@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:34:22 +0800 Subject: [PATCH 9/9] Add colorlog to project dependencies --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index ad3eaa9..e11810c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,7 @@ description = "Add your descriptions here" dependencies = [ "numpy", "pandas", + "colorlog", ] authors = [ {name = "Example Person", email = "someone@example.com"},