feat: bound one-shot –cmd runs with –timeout (#32)
Streaming commands (watch, trace, tt, gilstat) only return once their -n display limit is reached. When the observed function is never invoked – idle service, wrong worker process, wrong module – the command never returns. An interactive user presses Ctrl-C; a script, CI job or AI coding agent has no such escape and either blocks forever or kills the client.
Killing the client is the worse outcome: watch and trace install AOP instrumentation inside the target process, and only the client’s exit path removes it again. A SIGKILLed client leaves a production process permanently instrumented.
–timeout SECONDS raises KeyboardInterrupt in the main thread, which is exactly what Ctrl-C does, so the existing ProfilerCli.do_action handler runs BaseCliPlugin.on_interrupted and the target is left clean. The client then exits 124, the code GNU timeout uses for the same situation.
PYFLIGHT_CMD_TIMEOUT sets a default without touching every call site. The flag wins over the env var, and both are rejected outside –cmd so an exported default cannot cut short an interactive REPL session.
Skills for attach, watch and trace now document the flag, since agents constructing commands are the callers most exposed to the hang.
Signed-off-by: bppps bpppsaka@gmail.com
版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9
京公网安备 11010802047560号
PyFlightProfiler
📡 Breaking: AI-Powered Diagnostics
From manual CLI debugging to AI-assisted diagnostics — PyFlightProfiler now integrates with AI coding agents. Install the skills and let your AI assistant diagnose live Python processes through natural language.
Built-in support: Claude Code | Gemini CLI | Codex — other agents can also use these skills via specific directory installation.
flight-profiler-attachflight-profiler-watchflight-profiler-traceflight-profiler-stackflight-profiler-getglobalflight-profiler-vmtoolflight-profiler-reloadflight-profiler-moduleBackground
The growing demand for AI inference and agent-based applications has led to an increased deployment of Python systems in production environments. Inference services frequently encounter performance bottlenecks, while agent-based services face challenges in troubleshooting complex business logic. Production issues are often difficult to reproduce and debug, and traditional logging-based diagnostics typically result in prolonged investigation cycles with limited efficiency. PyFlightProfiler is designed to help address some of these common pain points.
What is PyFlightProfiler
PyFlightProfiler is a toolbox that lets you inspect the status of a running Python process. It allows developers to observe method execution, trace call paths, monitor GIL status, and more, without restarting the application.
What PyFlightProfiler can do
PyFlightProfiler has the following amazing features:
What platforms are supported
PyFlightProfiler currently supports Linux x86_64 (glibc ≥ 2.17) and macOS (arm64), and requires Python 3.8 or later.
Installation
To install PyFlightProfiler, simply use pip:
Documentation
You can find the full documentation here.
Usage
For a Python process to be profiled, PyFlightProfiler must reside in the same Python environment. Only then can the process correctly reference the flight_profiler library once attached. PyFlightProfiler follows a two-stage attach-then-profile workflow. After attaching to a target process, you can use various subcommands to inspect and debug your Python program in real time.
Attaching to a Running Process
The first step for attachment is to use the
flight_profilercommand followed by the PID of the process you want to analyze.--timeoutmatters for anything non-interactive. Streaming commands such aswatch,traceandttrun until their display limit is reached, which never happens if the observed function is not called — so a script, CI job or AI agent would wait forever. With a deadline the run stops the same way Ctrl-C does: the instrumentation is removed from the target process and the client exits 124, the same code GNUtimeoutuses.For CPython 3.14 and above, we utilize sys.remote_exec for remote code execution, a feature introduced by PEP-0768. This approach is therefore largely safe.
In CPython 3.13 and earlier versions, the implementation of remote code execution differs between macOS and Linux. On macOS, we utilize LLDB to inject agent logic into the target process. On Linux, however, code is dispatched to the remote process via ptrace. This approach requires that the Linux distribution supports ptrace and that the SYS_PTRACE capability is enabled in Docker environments.
As a best practice, PyFlightProfiler should be comprehensively validated in a non-production environment to ensure stability and performance before being trusted with live services.
Watching Method Input and Output
For method location, PyFlightProfiler uses the format
module [class] method, where module corresponds to the import path as it appears in the program. For instance,__main__for top-level scripts executed directly,pkg_a.pkg_bwhen the code usesfrom pkg_a import pkg_b, andpkg_bwhen usingimport pkg_b. This simple module resolution scheme suffices for most use cases. If you know the file path of the target code but are unsure of its runtime module name, you can use the module subcommand (described below) to verify whether the module as well as the target method is loaded in the process. The[class]component is optional and should only be included when the method belongs to a class. It is omitted for standalone (non-class) functions.In addition, PyFlightProfiler provides mechanisms for method filtering (-f) and custom extraction of key properties (–expr). You can specify a Python expression that operates within a context where the effective function signature is (target, return_obj, cost, *args, **kwargs), and the expression you provide serves as the body of a return statement. Here,
targetrefers to the class instance if the method is bound (or None for standalone functions),return_objis the value returned by the method,costrepresents the execution time in milliseconds, andargsandkwargscorrespond to the positional and keyword arguments passed to the method, respectively. For concrete usage patterns, refer to the examples provided in the watch command below.Tracing Method Call Paths
The
tracesubcommand is used to inspect method execution time and its inner method call chain. It uses the same method location mechanism as described in the watch subcommand. The-i, --intervaloption sets the threshold (in milliseconds) for displaying inner method calls—only invocations with a cost greater than ${interval} will be shown, with a default value of 0.1 ms. A higher interval reduces the profiler’s impact on the original program. In practice, we observe an average runtime overhead of 5%–20%, depending on the chosen interval.Locating module with filepath
Use the
modulesubcommand to determine the correct module name for a given source file path. This is helpful when you know the file location but are unsure how it was imported.Other Subcommands
PyFlightProfiler includes several additional tools for advanced diagnostics:
help- Display help for any command.console- Launch an interactive Python console inside the target process.stack- Analyze Python thread stacks (based on pystack).tt, timetunnel- Observe method behavior across time (historical execution context).reload- Reload method implementation from the latest source file.getglobal- Inspect global variables in the target process.vmtool- Inspect live class instances and their attributes.perf- Sample CPU hotspots and generate flame graphs (based on py-spy).torch- Profile PyTorch operations using the pre-installed PyTorch profiler (based on pytorch).mem- Report memory usage statistics (based on pympler).gilstat- Monitor Python’s Global Interpreter Lock (GIL) contention and performance impact.Acknowledgements
PyFlightProfiler is inspired by the design of Arthas. The project is developed by Alibaba Group. The code is distributed under the Apache License (Version 2.0). This product contains various third-party components under other open-source licenses. See the
NOTICEfile for more information.The implementation of the trace subcommand is conceptually inspired by pyinstrument. The process attachment mechanism on Linux is inspired by linux-inject. Python bytecode transform mechanism is inspired by Python on-the-fly function update. The following open-source libraries and tools are used in PyFlightProfiler, either in their close-to-original form or as an inspiration: