Skip to content

fix(inference): 完善 CLI 工具并修复中文路径问题 - #29

Merged
dhjs0000 merged 5 commits into
mainfrom
feature/error-0x12/python-inference-backend
May 5, 2026
Merged

fix(inference): 完善 CLI 工具并修复中文路径问题#29
dhjs0000 merged 5 commits into
mainfrom
feature/error-0x12/python-inference-backend

Conversation

@error-0x12

@error-0x12 error-0x12 commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

变更内容

本 PR 包含以下改进:

1. 修复中文路径图像加载问题

  • 使用 cv2.imdecode 作为备用方案支持中文路径
  • 解决 Windows 上 OpenCV 中文路径编码问题

2. 优化导入路径

  • 调整 sys.path 插入方式确保正确导入 src 包
  • 修改所有导入语句使用 src 前缀避免相对导入错误

3. 完善项目配置

  • 添加 .gitignore 文件
  • 添加 Trae IDE 配置目录到忽略列表

测试

  • ✅ CLI 工具正常运行
  • ✅ 支持中文路径图像加载
  • ✅ 所有检测命令可用

相关文件

  • inference/src/cli.py - CLI 工具主入口
  • .gitignore - Git 忽略文件配置

由 Sourcery 提供的总结

改进 CLI 图像加载的健壮性,并新增基础的仓库忽略配置。

Bug 修复:

  • 通过添加基于 cv2.imdecode 的回退方案,确保在文件路径包含中文字符时图像加载仍能正常工作。

增强:

  • 在 CLI 图像加载器中,为图像加载失败添加错误处理和日志记录。

构建:

  • 添加 .gitignore 文件,将常见及编辑器相关的产物排除在版本控制之外。
Original summary in English

Summary by Sourcery

Improve CLI image loading robustness and add basic repository ignore configuration.

Bug Fixes:

  • Ensure image loading works for file paths containing Chinese characters by adding a cv2.imdecode-based fallback.

Enhancements:

  • Add error handling and logging around image loading failures in the CLI image loader.

Build:

  • Add a .gitignore file to exclude common and editor-specific artifacts from version control.

- 使用 cv2.imdecode 作为备用方案支持中文路径
- 调整 sys.path 插入方式确保正确导入 src 包
- 修改所有导入语句使用 src 前缀避免相对导入错误
- 从 main 分支同步 .gitignore 基础配置
- 添加 .trae/ 目录到 IDE 忽略列表
- 保持与主分支一致的忽略规则
@arknightsautomachine-ai-reviewer

arknightsautomachine-ai-reviewer Bot commented Apr 8, 2026

Copy link
Copy Markdown

Review Complete!

The code review has been posted. View Review →

@sourcery-ai

sourcery-ai Bot commented Apr 8, 2026

Copy link
Copy Markdown
审阅者指南(在小型 PR 中折叠)

审阅者指南

在 CLI 中添加了更健壮的图像加载逻辑,通过回退到 cv2.imdecode 来支持中文文件路径,并新增 .gitignore 以忽略项目配置和 IDE 产物。

支持中文路径的 CLI 图像加载时序图

sequenceDiagram
    actor User
    participant CLI
    participant ImageLoader
    participant cv2
    participant OS
    participant logging

    User->>CLI: run detection with image_path
    CLI->>ImageLoader: load(path)

    ImageLoader->>cv2: imread(str(path))
    cv2-->>ImageLoader: image_or_none

    alt image is None
        ImageLoader->>OS: open(path, rb)
        OS-->>ImageLoader: file_bytes
        ImageLoader->>cv2: imdecode(file_bytes, IMREAD_COLOR)
        cv2-->>ImageLoader: image_or_none
    end

    alt exception raised
        ImageLoader->>logging: error(加载图像失败...)
        ImageLoader-->>CLI: None
        CLI-->>User: report image load failure
    else image loaded
        ImageLoader-->>CLI: image
        CLI-->>User: continue detection pipeline
    end
Loading

更新后的 CLI 图像加载工具类图

classDiagram

    class ImageLoader {
        +SUPPORTED_EXTENSIONS
        +load(path: Path) np.ndarray
        +load_batch(directory: Path, recursive: bool) List~Tuple[Path, np.ndarray]~
    }

    class cv2
    class numpy
    class logging
    class Path

    ImageLoader ..> cv2 : uses
    ImageLoader ..> numpy : uses
    ImageLoader ..> logging : logs_errors
    ImageLoader ..> Path : takes
Loading

文件级改动

Change Details Files
加固 CLI 中的图像加载逻辑,以支持中文/Unicode 路径并改进错误处理。
  • 保持 cv2.imread 作为针对受支持图像扩展名的主路径加载器。
  • cv2.imread 失败时,回退为使用 open(...) 读取原始字节并通过 cv2.imdecode 解码,以更好地支持非 ASCII 路径(例如 Windows 上的中文路径)。
  • 将图像加载逻辑包裹在 try/except 块中,记录失败日志而不是抛出异常,出错时返回 None
inference/src/cli.py
为代码仓库引入 git ignore 规则,包括 IDE 配置。
  • 添加新的 .gitignore 文件,用于忽略构建产物以及编辑器/IDE 配置(包括 Trae IDE)。
.gitignore

提示和命令

与 Sourcery 交互

  • 触发一次新的审阅: 在 pull request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审阅评论。
  • 从审阅评论生成 GitHub issue: 在某条审阅评论下回复,要求 Sourcery 从该评论创建一个 issue。你也可以在该审阅评论下回复 @sourcery-ai issue 来从中创建 issue。
  • 生成 pull request 标题: 在 pull request 标题的任意位置写上 @sourcery-ai,即可随时生成标题。你也可以在 pull request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 pull request 摘要: 在 pull request 正文的任意位置写上 @sourcery-ai summary,即可在你想要的位置随时生成 PR 摘要。你也可以在 pull request 中评论 @sourcery-ai summary 来(重新)生成摘要。
  • 生成审阅者指南: 在 pull request 中评论 @sourcery-ai guide,即可在任意时间(重新)生成审阅者指南。
  • 解决所有 Sourcery 评论: 在 pull request 中评论 @sourcery-ai resolve,即可将所有 Sourcery 评论标记为已解决。如果你已经处理完所有评论且不想再看到它们,这会非常有用。
  • 撤销所有 Sourcery 审阅: 在 pull request 中评论 @sourcery-ai dismiss,即可撤销所有现有的 Sourcery 审阅。尤其适用于你想从头开始一次新的审阅的情况——别忘了再评论 @sourcery-ai review 来触发新的审阅!

自定义你的体验

访问你的 控制面板 以:

  • 启用或禁用诸如 Sourcery 生成的 pull request 摘要、审阅者指南等审阅功能。
  • 更改审阅语言。
  • 添加、移除或编辑自定义审阅指令。
  • 调整其他审阅设置。

获取帮助

Original review guide in English
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adds more robust image loading in the CLI to support Chinese file paths by falling back to cv2.imdecode and introduces a new .gitignore for project configuration and IDE artifacts.

Sequence diagram for CLI image loading with Chinese path support

sequenceDiagram
    actor User
    participant CLI
    participant ImageLoader
    participant cv2
    participant OS
    participant logging

    User->>CLI: run detection with image_path
    CLI->>ImageLoader: load(path)

    ImageLoader->>cv2: imread(str(path))
    cv2-->>ImageLoader: image_or_none

    alt image is None
        ImageLoader->>OS: open(path, rb)
        OS-->>ImageLoader: file_bytes
        ImageLoader->>cv2: imdecode(file_bytes, IMREAD_COLOR)
        cv2-->>ImageLoader: image_or_none
    end

    alt exception raised
        ImageLoader->>logging: error(加载图像失败...)
        ImageLoader-->>CLI: None
        CLI-->>User: report image load failure
    else image loaded
        ImageLoader-->>CLI: image
        CLI-->>User: continue detection pipeline
    end
Loading

Updated class diagram for the CLI image loading utility

classDiagram

    class ImageLoader {
        +SUPPORTED_EXTENSIONS
        +load(path: Path) np.ndarray
        +load_batch(directory: Path, recursive: bool) List~Tuple[Path, np.ndarray]~
    }

    class cv2
    class numpy
    class logging
    class Path

    ImageLoader ..> cv2 : uses
    ImageLoader ..> numpy : uses
    ImageLoader ..> logging : logs_errors
    ImageLoader ..> Path : takes
Loading

File-Level Changes

Change Details Files
Harden image loading in CLI to support Chinese/Unicode paths and improve error handling.
  • Keep cv2.imread as primary path-based loader for supported image extensions.
  • On cv2.imread failure, fall back to reading raw bytes with open(...) and decoding via cv2.imdecode to better support non-ASCII paths (e.g., Chinese paths on Windows).
  • Wrap image loading in a try/except block and log failures instead of raising, returning None on error.
inference/src/cli.py
Introduce git ignore rules for the repository, including IDE configuration.
  • Add a new .gitignore file to ignore build artifacts and editor/IDE configuration (including Trae IDE).
.gitignore

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 Summary

本次 PR 修复了推理层 CLI 工具的中文路径支持问题,并优化了导入路径结构。变更涉及 L1 感知层(inference/src/cli.py)和项目配置(.gitignore)。

File Changes Risk Level Status
.gitignore +475/-0 🟢 Low Added
inference/src/cli.py +23/-6 🟡 Medium Modified

变更要点

  1. 中文路径修复:使用 cv2.imdecode 作为 OpenCV imread 的备用方案,解决 Windows 中文路径编码问题
  2. 导入路径优化:调整 sys.path 插入逻辑,确保 src 包可被正确导入
  3. 完善依赖导入:补充了 SquadRecognizerSquadAnalyzerOperatorMatcher 等类的显式导入

🚨 Critical Issues (Must Fix)

[AGPL-3.0 Compliance] inference/src/cli.py 文件头缺少 AGPL-3.0 许可证声明

根据项目规范,所有修改的文件必须保留版权声明。由于 diff 从第 41 行开始显示,无法确认文件头是否存在许可证。请确保文件顶部包含以下标准头:

// =============================================================================
// Copyright (C) 2026 Ethernos Studio
// This file is part of Arknights Auto Machine (AAM).
//
// AAM is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// AAM is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with AAM. If not, see <https://www.gnu.org/licenses/>.
// =============================================================================
// @author error-0x12
// @brief CLI 工具主入口
// =============================================================================

⚠️ Warnings (Should Fix)

[Error Handling] 过于宽泛的异常捕获

使用 except Exception: 会捕获包括 KeyboardInterrupt 在内的所有异常,可能导致用户无法通过 Ctrl+C 中断程序。


💡 Suggestions

[Import Style] 导入组织

第 69-81 行的导入语句较长,建议按标准库/第三方库/本地模块分组,并考虑使用 TYPE_CHECKING 减少运行时导入开销(如仅在类型检查时需要)。


📍 Inline Comments


Open Questions

  • License Header: 请确认 cli.py 第 1-40 行是否已包含 AGPL-3.0 许可证头?如未包含,需补充。
  • Import Testing: 新的 src. 前缀导入是否在虚拟环境和直接运行 (python cli.py) 两种场景下均测试通过?

🤖 Copy this prompt for AI Agent
Please address the comments from this code review:

## Overall Comments
1. Add AGPL-3.0 license header to inference/src/cli.py if missing (lines 1-40 not shown in diff)
2. Fix broad exception handling at line 252 - use specific exceptions (IOError, OSError) instead of Exception
3. Consider adding path cleanup after imports or use context manager for sys.path modification at line 45

## File-specific Changes
- File: inference/src/cli.py, Line 252: Replace `except Exception as e:` with `except (IOError, OSError) as e:` to avoid catching KeyboardInterrupt
- File: inference/src/cli.py, Line 45: Add try-finally block to restore sys.path after imports, or document why this side effect is safe
- File: inference/src/cli.py, Line 250: Add None check after cv2.imdecode and log appropriate warning

## Context
This PR fixes Chinese path support in OpenCV image loading and reorganizes imports to use src package prefix. Ensure the fix doesn't break existing import chains.

Thank you!

统计: 2 🚨 | 2 ⚠️ | 2 💡

This review was generated by ArknightsAutoMachine AI Reviewer

Comment thread inference/src/cli.py Outdated
file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8)
image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
return image
except Exception as e:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 [Critical] 过于宽泛的异常捕获。应捕获具体异常类型如 (IOError, OSError, cv2.error),避免捕获 KeyboardInterruptSystemExit。建议修改为:

except (IOError, OSError) as e:
    logging.error(f"加载图像失败:{e}")
    return None

Comment thread inference/src/cli.py
# 确保src目录在路径中
sys.path.insert(0, str(Path(__file__).parent))
# 确保 src 目录的父目录在路径中(这样 src 可以作为包导入)
parent_path = str(Path(__file__).parent.parent)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [Warning] sys.path 修改可能影响其他模块导入顺序。建议在导入完成后移除路径修改,或使用 try-finally 确保路径清理,避免副作用泄漏到调用方。

Comment thread inference/src/cli.py Outdated
# 如果失败,尝试用文件流方式读取(支持中文路径)
with open(path, 'rb') as f:
file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8)
image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 [Suggestion] cv2.imdecode 在图像无效时返回 None,建议添加对 image is None 的检查并记录警告日志,区分"文件读取失败"和"图像解码失败"两种情况。

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 2 个问题,并给出了一些高层次的反馈:

  • 在图片加载逻辑中,建议捕获更具体的异常(如 OSErrorcv2.error),而不是宽泛地捕获 Exception,这样在调试时仍然可以暴露出意料之外的错误。
  • 你可以使用 pathlib 中的 path.read_bytes() 来简化回退分支,而不是手动打开文件并读取到一个 bytearray,这样可以让代码更简洁、更符合 Python 惯用写法。
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the image loading logic, consider catching more specific exceptions (e.g., `OSError`, `cv2.error`) instead of a broad `Exception` so that unexpected errors still surface during debugging.
- You can simplify the fallback branch by using `path.read_bytes()` from `pathlib` instead of manually opening the file and reading into a bytearray, which will keep the code shorter and more idiomatic.

## Individual Comments

### Comment 1
<location path="inference/src/cli.py" line_range="243-252" />
<code_context>
-        image = cv2.imread(str(path))
-        return image
+        # 使用 cv2.imdecode 读取图像以支持中文路径
+        try:
+            # 先用普通方式读取
+            image = cv2.imread(str(path))
+            if image is None:
+                # 如果失败,尝试用文件流方式读取(支持中文路径)
+                with open(path, 'rb') as f:
+                    file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8)
+                    image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
+            return image
+        except Exception as e:
+            logging.error(f"加载图像失败:{e}")
+            return None
</code_context>
<issue_to_address>
**issue (bug_risk):** Use more specific exception handling or at least avoid catching bare `Exception`.

This will also hide programming errors (e.g., `TypeError`, `ValueError`) that should surface as real bugs. Please narrow the `except` to the expected I/O/decoding errors (e.g., `OSError`, `cv2.error`), or re-raise unexpected exceptions after logging so they don’t fail silently.
</issue_to_address>

### Comment 2
<location path="inference/src/cli.py" line_range="252-253" />
<code_context>
+                    file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8)
+                    image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
+            return image
+        except Exception as e:
+            logging.error(f"加载图像失败:{e}")
+            return None

</code_context>
<issue_to_address>
**suggestion:** Include exception details in the log via `exc_info` for better debugging.

Currently only the exception message is logged, so you lose the traceback. Please log with traceback preserved, e.g. `logging.exception("加载图像失败")` or `logging.error("加载图像失败", exc_info=True)`, while still returning `None` to the caller.

Suggested implementation:

```python
        # 使用 cv2.imdecode 读取图像以支持中文路径
        try:
            # 先用普通方式读取
            image = cv2.imread(str(path))
            if image is None:
                # 如果失败,尝试用文件流方式读取(支持中文路径)
                with open(path, 'rb') as f:
                    file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8)
                    image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
            return image
        except Exception:
            logging.exception("加载图像失败")
            return None

```

1. Ensure `import logging` exists at the top of `inference/src/cli.py`. If it does not, add:
   `import logging`
2. If this code is inside a function/method, confirm the indentation of the `except` block matches the `try` block's scope.
</issue_to_address>

Sourcery 对开源项目是免费的——如果你觉得我们的评审对你有帮助,欢迎分享给更多人 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的评审。
Original comment in English

Hey - I've found 2 issues, and left some high level feedback:

  • In the image loading logic, consider catching more specific exceptions (e.g., OSError, cv2.error) instead of a broad Exception so that unexpected errors still surface during debugging.
  • You can simplify the fallback branch by using path.read_bytes() from pathlib instead of manually opening the file and reading into a bytearray, which will keep the code shorter and more idiomatic.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the image loading logic, consider catching more specific exceptions (e.g., `OSError`, `cv2.error`) instead of a broad `Exception` so that unexpected errors still surface during debugging.
- You can simplify the fallback branch by using `path.read_bytes()` from `pathlib` instead of manually opening the file and reading into a bytearray, which will keep the code shorter and more idiomatic.

## Individual Comments

### Comment 1
<location path="inference/src/cli.py" line_range="243-252" />
<code_context>
-        image = cv2.imread(str(path))
-        return image
+        # 使用 cv2.imdecode 读取图像以支持中文路径
+        try:
+            # 先用普通方式读取
+            image = cv2.imread(str(path))
+            if image is None:
+                # 如果失败,尝试用文件流方式读取(支持中文路径)
+                with open(path, 'rb') as f:
+                    file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8)
+                    image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
+            return image
+        except Exception as e:
+            logging.error(f"加载图像失败:{e}")
+            return None
</code_context>
<issue_to_address>
**issue (bug_risk):** Use more specific exception handling or at least avoid catching bare `Exception`.

This will also hide programming errors (e.g., `TypeError`, `ValueError`) that should surface as real bugs. Please narrow the `except` to the expected I/O/decoding errors (e.g., `OSError`, `cv2.error`), or re-raise unexpected exceptions after logging so they don’t fail silently.
</issue_to_address>

### Comment 2
<location path="inference/src/cli.py" line_range="252-253" />
<code_context>
+                    file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8)
+                    image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
+            return image
+        except Exception as e:
+            logging.error(f"加载图像失败:{e}")
+            return None

</code_context>
<issue_to_address>
**suggestion:** Include exception details in the log via `exc_info` for better debugging.

Currently only the exception message is logged, so you lose the traceback. Please log with traceback preserved, e.g. `logging.exception("加载图像失败")` or `logging.error("加载图像失败", exc_info=True)`, while still returning `None` to the caller.

Suggested implementation:

```python
        # 使用 cv2.imdecode 读取图像以支持中文路径
        try:
            # 先用普通方式读取
            image = cv2.imread(str(path))
            if image is None:
                # 如果失败,尝试用文件流方式读取(支持中文路径)
                with open(path, 'rb') as f:
                    file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8)
                    image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
            return image
        except Exception:
            logging.exception("加载图像失败")
            return None

```

1. Ensure `import logging` exists at the top of `inference/src/cli.py`. If it does not, add:
   `import logging`
2. If this code is inside a function/method, confirm the indentation of the `except` block matches the `try` block's scope.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread inference/src/cli.py Outdated
Comment on lines +243 to +252
try:
# 先用普通方式读取
image = cv2.imread(str(path))
if image is None:
# 如果失败,尝试用文件流方式读取(支持中文路径)
with open(path, 'rb') as f:
file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8)
image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
return image
except Exception as e:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): 使用更具体的异常处理,或者至少避免捕获裸 Exception

这样会把一些编程错误(例如 TypeErrorValueError)也一起吞掉,而这些错误本应作为真实 bug 暴露出来。请将 except 缩小到预期的 I/O/解码类错误(例如 OSErrorcv2.error),或者在日志记录后对意料之外的异常重新抛出,这样它们就不会静默失败。

Original comment in English

issue (bug_risk): Use more specific exception handling or at least avoid catching bare Exception.

This will also hide programming errors (e.g., TypeError, ValueError) that should surface as real bugs. Please narrow the except to the expected I/O/decoding errors (e.g., OSError, cv2.error), or re-raise unexpected exceptions after logging so they don’t fail silently.

Comment thread inference/src/cli.py Outdated
Comment on lines +252 to +253
except Exception as e:
logging.error(f"加载图像失败:{e}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: 在日志中通过 exc_info 一并记录异常细节,以便更好地调试。

目前只记录了异常消息本身,堆栈追踪信息会丢失。请在保留 traceback 的情况下记录日志,例如使用 logging.exception("加载图像失败")logging.error("加载图像失败", exc_info=True),同时仍然向调用方返回 None

建议实现如下:

        # 使用 cv2.imdecode 读取图像以支持中文路径
        try:
            # 先用普通方式读取
            image = cv2.imread(str(path))
            if image is None:
                # 如果失败,尝试用文件流方式读取(支持中文路径)
                with open(path, 'rb') as f:
                    file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8)
                    image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
            return image
        except Exception:
            logging.exception("加载图像失败")
            return None
  1. 确认 inference/src/cli.py 文件顶部已经有 import logging。如果没有,请添加:
    import logging
  2. 如果这段代码位于函数/方法内部,请确认 except 代码块的缩进层级与 try 保持一致。
Original comment in English

suggestion: Include exception details in the log via exc_info for better debugging.

Currently only the exception message is logged, so you lose the traceback. Please log with traceback preserved, e.g. logging.exception("加载图像失败") or logging.error("加载图像失败", exc_info=True), while still returning None to the caller.

Suggested implementation:

        # 使用 cv2.imdecode 读取图像以支持中文路径
        try:
            # 先用普通方式读取
            image = cv2.imread(str(path))
            if image is None:
                # 如果失败,尝试用文件流方式读取(支持中文路径)
                with open(path, 'rb') as f:
                    file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8)
                    image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
            return image
        except Exception:
            logging.exception("加载图像失败")
            return None
  1. Ensure import logging exists at the top of inference/src/cli.py. If it does not, add:
    import logging
  2. If this code is inside a function/method, confirm the indentation of the except block matches the try block's scope.

- 添加 AGPL-3.0 许可证头到文件顶部
- 修复过于宽泛的异常捕获,使用具体异常类型
  * 图像加载:使用 (IOError, OSError, ValueError)
  * 主函数:添加 (SystemExit, EOFError) 处理
- 优化导入组织方式
  * 按标准库/第三方库/本地模块分组
  * 本地模块按 Vision/Data 分类
  * 字母排序提高可读性
- 修复命名冲突:OperatorMatcher.MatchResult 重命名为 OperatorMatchResult

回应 AI Reviewer 提出的改进建议
@arknightsautomachine-ai-reviewer

arknightsautomachine-ai-reviewer Bot commented Apr 10, 2026

Copy link
Copy Markdown

Review Complete!

The code review has been posted. View Review →

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 Summary

本次 PR 修复了 inference 模块 CLI 工具的中文路径支持问题,并优化了导入结构。PR 作者为 error-0x12,代码变更符合 ROADMAP 中 v0.5.0-alpha Python L1 感知层的已完成状态。

File Changes Risk Level Status
.gitignore +475/-0 🟢 Low Added
inference/src/cli.py +77/-28 🟡 Medium Modified

🏗️ 架构合规性

  • 层级: L1 (Perception) - 视觉处理与 CLI 接口
  • 位置: inference/src/cli.py 属于 Python 后端,符合 ROADMAP v0.5.0-alpha 已完成项
  • 导入修复: sys.path 调整正确,支持 src 作为包导入

🚨 Critical Issues (Must Fix)

[File: inference/src/cli.py, Line: 2666] 错误处理 SystemExit
捕获 SystemExit 会阻止程序正常退出码的传播。当代码调用 sys.exit(0)(正常退出)时,当前实现会将其记录为错误并返回 1(失败状态)。

# 错误代码:
except (SystemExit, EOFError) as e:
    logger.error(f"程序错误:{e}")
    return 1

# 修复建议:
except SystemExit:
    raise  # 重新抛出,保留原始退出码
except EOFError as e:
    logger.error(f"输入错误:{e}")
    return 1

或完全移除 SystemExit 捕获,让 Python 解释器正常处理程序退出。


⚠️ Warnings (Should Fix)

[File: inference/src/cli.py, Line: 271-283] 图像加载异常处理
虽然 cv2.imdecode 回退方案正确,但建议区分"文件不存在"和"解码失败"的不同错误类型,以便用户排查问题。


💡 Suggestions

  1. 导入组织: 将导入分为标准库、第三方库、本地模块的做法很好,符合 PEP 8 规范
  2. AGPL 头: 新添加的文件头正确,作者信息匹配
  3. 中文路径支持: 使用 np.fromfilecv2.imdecode 处理中文路径是 Windows 上的标准解决方案,实现正确

📍 Inline Comments


Open Questions

  • SystemExit 处理: 是否有特定原因需要捕获 SystemExit?如果没有,建议移除以遵循 Python 最佳实践。

🤖 Copy this prompt for AI Agent

Please address the comments from this code review:

Overall Comments

  1. Fix SystemExit handling (Critical): Remove SystemExit from the exception tuple at line 2666 in cli.py, or handle it separately by re-raising to preserve exit codes. Catching SystemExit prevents proper program termination.
  2. Improve error messages: Distinguish between file-not-found errors and image decoding errors in the load_image method for better user experience.

File-specific Changes

  • File: inference/src/cli.py
    • Line 2666: Remove SystemExit from the exception tuple except (SystemExit, EOFError). If cleanup is needed, use a finally block instead.
    • Line 271-283: Enhance error logging to specify whether the failure was due to file access issues or image decoding problems.

The import path fix and Chinese path support implementation are correct and should be kept.

Thank you!


统计: 2 🚨 | 2 ⚠️ | 2 💡

This review was generated by ArknightsAutoMachine AI Reviewer

Comment thread inference/src/cli.py Outdated
except KeyboardInterrupt:
logger.info("用户中断")
return 130
except (SystemExit, EOFError) as e:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 [Critical] 捕获 SystemExit 会导致退出码丢失。如果程序其他位置调用 sys.exit(0) 表示成功退出,此处会错误地记录为错误并返回 1。建议单独处理或移除 SystemExit 捕获,使用 finally 块进行清理操作。

Comment thread inference/src/cli.py

image = cv2.imread(str(path))
return image
# 使用 cv2.imdecode 读取图像以支持中文路径

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [Warning] 图像加载回退方案正确,但建议将 IOErrorValueError 分开处理:IOError 通常表示文件不存在或权限问题,ValueError 表示解码失败,不同错误应提供不同的用户提示。

Comment thread inference/src/cli.py
# 确保src目录在路径中
sys.path.insert(0, str(Path(__file__).parent))
# 确保 src 目录的父目录在路径中(这样 src 可以作为包导入)
parent_path = str(Path(__file__).parent.parent)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 [Suggestion] sys.path 修复正确。使用 parent.parent 确保 inference/ 目录在路径中,使 src 可以作为包导入,解决了相对导入问题。

- 移除 SystemExit 异常捕获,保留 Python 正常退出机制
  * 避免阻止 sys.exit() 退出码传播
  * 仅保留 EOFError 处理输入错误
- 改进图像加载错误信息
  * 文件不存在:记录具体路径
  * 文件格式不支持:记录文件扩展名
  * 图像解码失败:区分读取错误和解码错误
  * 所有错误信息包含完整路径便于排查

回应 AI Reviewer 第二轮审查意见
@arknightsautomachine-ai-reviewer

arknightsautomachine-ai-reviewer Bot commented Apr 10, 2026

Copy link
Copy Markdown

Review Complete!

The code review has been posted. View Review →

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 Summary

这是一个高质量的修复性 PR,作者 error-0x12 针对 CLI 工具进行了三项重要改进:

  1. 中文路径支持:使用 cv2.imdecode 作为 cv2.imread 的备用方案,解决了 Windows 上 OpenCV 中文路径编码问题
  2. 导入路径优化:修正 sys.path 插入逻辑,确保 src 可作为包正确导入,避免了相对导入错误
  3. 错误处理增强:添加了 EOFError 和文件 I/O 异常的捕获,提升了 CLI 的健壮性

此外,新增的 .gitignore 文件配置全面,涵盖了 C++、Python、C#、多种 IDE(包括 Trae)的忽略规则。

File Changes Risk Level Status
inference/src/cli.py +85/-28 🟡 Medium Modified
.gitignore +475/-0 🟢 Low Added

✅ 审查通过

代码质量:优秀。修复逻辑严谨,异常处理完整,类型提示规范。

架构合规:符合 L1 感知层定位,变更仅限于 CLI 工具内部实现细节,未破坏分层架构。

AGPL 合规cli.py 已包含完整的 AGPL-3.0 许可证头,且 @author 字段与 PR 作者一致。

ROADMAP 状态:此为 v0.5.0-alpha(Python L1 视觉层)的修复优化,不涉及新功能开发,无需更新 ROADMAP 勾选状态。


💡 建议(非阻塞)

  1. 图像加载验证:当前在 cv2.imdecode 失败后记录错误并返回 None,建议考虑在日志中区分是"文件读取失败"还是"图像解码失败",以便调试。

  2. 路径假设parent_path = Path(__file__).parent.parent 假设了文件位于 inference/src/cli.py,若未来移动文件位置需同步调整。可考虑添加注释说明。


📍 Inline Comments

无阻塞性问题,无需内联评论。


Open Questions

  • 无待解决问题

审查结论:✅ Approved - 代码符合生产环境标准,可以合并。


统计: 0 🚨 | 0 ⚠️ | 1 💡

This review was generated by ArknightsAutoMachine AI Reviewer

@arknightsautomachine-ai-reviewer

arknightsautomachine-ai-reviewer Bot commented Apr 10, 2026

Copy link
Copy Markdown

Review Complete!

The code review has been posted. View Review →

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 Summary

本次 PR 由 error-0x12 提交,针对 inference/src/cli.py 进行了以下改进:

  1. AGPL 合规性:添加了标准的 AGPL-3.0 文件头,包含版权声明和作者信息(@author error-0x12 ✅)
  2. 中文路径修复:使用 cv2.imdecode 作为 fallback 方案,解决 Windows 上 OpenCV 无法读取中文路径的问题
  3. 导入路径优化:调整 sys.path 插入逻辑,确保 src 包正确导入
  4. 错误处理增强:添加 EOFError 捕获和更详细的日志记录
  5. 开发环境配置:添加 .gitignore 忽略 Trae IDE 配置目录
File Changes Risk Level Status
.gitignore +3/-0 🟢 Low Modified
inference/src/cli.py +85/-28 🟡 Medium Modified

架构合规性检查

  • L1 视觉层调用:CLI 工具调用 src.visionsrc.data 符合 L1/L4 分层架构(✅)
  • 无跨层违规:未出现 L5 直接调用 L0 等违规情况(✅)

代码质量评估

  • 中文路径处理cv2.imdecode 方案是处理 Windows 中文路径的标准做法(✅)
  • 错误处理:新增的 EOFError 捕获完善了 CLI 的健壮性(✅)
  • 导入顺序:标准库 → 第三方库 → 本地模块的顺序符合 PEP 8(✅)

📝 ROADMAP Update Reminder

此 PR 完善了 v0.5.0-alpha(视觉皮层版)的 CLI 工具。若这是该版本的最终修复,请确保在 ROADMAP.md 中检查相关测试验收项:

  • inference/src/cli.py 功能测试通过(中文路径支持)

💡 Suggestions

虽然代码整体质量良好,但以下细节可以进一步优化:

  1. 路径处理注释:建议在 parent_path 处理处添加更详细的注释,说明为何需要 parent.parent(指向 inference/ 目录)

  2. 日志级别:中文路径 fallback 成功时,建议添加 logging.debug 记录使用了备用加载方式,便于后续调试

  3. 类型提示ImageLoader.load 返回类型已标注为 Optional[np.ndarray],建议同时标注参数类型 path: Union[str, Path] 以支持更灵活的调用


✅ 结论

此 PR 可以合并。

代码符合 AGPL-3.0 规范,正确修复了 Windows 中文路径问题,作者信息标注正确,无架构违规,无生产环境风险。

建议操作:合并后请在 ROADMAP-S.md 的 v0.5.0-alpha 章节中更新 CLI 工具测试状态。


🤖 Copy this prompt for AI Agent
Please address the comments from this code review:

## Overall Comments
1. Add debug logging when cv2.imdecode fallback is used for Chinese path support (line ~310)
2. Consider adding type hint Union[str, Path] for the path parameter in ImageLoader.load
3. Add comment explaining why parent.parent is needed for sys.path insertion (line ~71)

## File-specific Changes
- File: inference/src/cli.py
  - Line 71: Add comment explaining the path manipulation
  - Line 310: Add logging.debug("Using imdecode fallback for Chinese path support")
  - Line 293: Consider updating type hint for path parameter

No critical issues found. The PR is ready to merge after these minor improvements.
Thank you!

统计: 0 🚨 | 0 ⚠️ | 1 💡

This review was generated by ArknightsAutoMachine AI Reviewer

Comment thread inference/src/cli.py
from typing import Optional, List, Dict, Any, Callable, Tuple
from dataclasses import dataclass, asdict
from enum import Enum
import os
Comment thread inference/src/cli.py
MainMenuAnalyzer,
UIElement,
UIElementType,
from src.vision.squad_analyzer import SquadAnalysisResult, SquadAnalyzer
Comment thread inference/src/cli.py
from src.vision.squad_recognizer import SquadRecognizer, SquadConfig
from src.vision.squad_analyzer import SquadAnalyzer
from src.data.models import Item, Operator, Stage
from src.data.operator_matcher import MatchResult as OperatorMatchResult
@dhjs0000
dhjs0000 merged commit fd9f7b5 into main May 5, 2026
5 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants