diff --git a/pyproject.toml b/pyproject.toml index e21c549..516c790 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,7 @@ packtool = "pyflowx.cli.packtool:main" pdftool = "pyflowx.cli.pdftool:main" piptool = "pyflowx.cli.piptool:main" pymake = "pyflowx.cli.pymake:main" +pxp = "pyflowx.cli.profiler:main" reseticon = "pyflowx.cli.reseticoncache:main" scrcap = "pyflowx.cli.screenshot:main" sglang = "pyflowx.cli.llm.sglang:main" diff --git a/src/pyflowx/cli/profiler.py b/src/pyflowx/cli/profiler.py new file mode 100644 index 0000000..53e4aeb --- /dev/null +++ b/src/pyflowx/cli/profiler.py @@ -0,0 +1,272 @@ +"""pxp —— PyFlowX 性能分析器. + +分析包含 ``px`` 调用的 Python 脚本,生成工作流执行性能剖面报告。 + +工作原理 +-------- +1. 注入 hook:monkey-patch ``pyflowx.run`` / ``pyflowx.executors.run`` / + ``pyflowx.runner.run``,捕获最后一次执行的 ``Graph`` 与 ``RunReport``。 +2. 执行目标脚本:用 ``runpy.run_path`` 以 ``__main__`` 身份执行, + 捕获 ``SystemExit``(脚本可能调 ``sys.exit``)。 +3. 生成报告:从捕获的 report + graph 构建 :class:`ProfileReport`, + 默认输出 HTML 并自动打开浏览器。 + +使用方式 +-------- + # 分析 pymake.py,生成 HTML 报告并打开浏览器 + pxp pymake.py + + # 传递参数给被分析脚本(用 -- 分隔) + pxp pymake.py -- t + + # 指定输出文件 + pxp pymake.py -o report.html + + # 不打开浏览器 + pxp pymake.py --no-browser + + # 输出纯文本报告 + pxp pymake.py -E text +""" + +from __future__ import annotations + +__all__ = ["main"] + +import argparse +import runpy +import sys +import webbrowser +from pathlib import Path +from typing import Any + +from .. import executors as _executors +from .. import runner as _runner +from ..profiling import ProfileReport +from ..report import RunReport + + +def _build_parser() -> argparse.ArgumentParser: + """构建参数解析器。""" + parser = argparse.ArgumentParser( + prog="pxp", + description="PyFlowX 性能分析器:分析包含 px 调用的脚本,生成性能剖面报告。", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=( + "示例:\n" + " pxp pymake.py # 分析并打开 HTML 报告\n" + " pxp pymake.py -- t # 传递参数 t 给脚本\n" + " pxp pymake.py -E text # 输出纯文本报告\n" + " pxp pymake.py -o out.html # 指定输出文件\n" + ), + ) + _ = parser.add_argument( + "--export", + "-E", + choices=["html", "text"], + default="html", + help="导出格式(默认: html)", + ) + _ = parser.add_argument( + "--no-browser", + action="store_true", + help="不自动打开浏览器(仅 HTML 格式有效)", + ) + _ = parser.add_argument( + "-o", + "--output", + help="输出文件路径(默认: