Prerequisites and connection details for attaching to a live Python process with PyFlightProfiler. Read this skill first before using any other PyFlightProfiler command (watch, trace, stack, perf, etc.).
中文简介正在准备中。当前显示原文说明。
Inspect stack frames of a running Python process including thread stacks, native C-level frames, and async coroutine stacks. Use this to see what each thread is currently doing and diagnose hangs, deadlocks, or stuck async tasks.
中文简介正在准备中。当前显示原文说明。
查看安装方法安装前可以查看交给 AI 代理的指令内容。
Inspect stack frames of the current running process. Essential for diagnosing hangs, deadlocks, and understanding what the process is doing right now. This is a non-streaming command — it captures a snapshot and returns immediately.
Prerequisites: Read the flight-profiler-attach skill first for platform requirements, installation, permissions, and connection details.
module, watch, and trace command argumentsflight_profiler <pid> --cmd "stack [options]" --no-color
| Flag | Platform | Description | Default |
|---|---|---|---|
--native | Linux only | Display native (C-level) stack frames via pystack | off |
-a, --async | Both | Display async coroutine/task stacks | off |
-f, --filepath <value> | Both | Redirect stack output to file | none |
Each thread produces a traceback block:
Traceback for thread <tid> (<interpreter>) [<GIL status>] (most recent call last):
(Python) File "<filename>", line <lineno>, in <funcname>
<source_line>
| Field | Description |
|---|---|
tid | OS thread ID (numeric) |
interpreter | Interpreter name (usually python) |
GIL status | Has the GIL, Waiting for the GIL, or empty [] |
(Python) | Indicates a Python-level frame |
(C) | Indicates a native C-level frame (only with --native) |
File ... | Source file, line number, and function name |
| Source line | The actual source code at that frame |
On macOS, thread stacks are fetched via the injected server using CPython's _Py_DumpTracebackThreads. Thread names are automatically added:
(<thread_name>) 0x<hex_tid> (most recent call first):
File "<filename>", line <lineno> in <funcname>
Note: macOS output uses "most recent call first" (reverse order), while Linux pystack uses "most recent call last" (Python traceback convention).
-a)When -a is used, the output shows all active asyncio tasks grouped by the thread running their event loop:
============================================================
Async Coroutine/Task Stacks
============================================================
Thread: <thread_name> (tid: 0x<hex_tid>)
--------------------------------------------------
Task #1: <task_name>
State: <state>
Coroutine: <qualname>
Stack (<N> frames):
File "<filename>", line <lineno>, in <funcname>
<source_line>
============================================================
| Field | Description |
|---|---|
Thread | Thread name and hex TID running the event loop |
Task #N | Task index and name (from asyncio.create_task(name=...)) |
State | PENDING, WAITING, FINISHED, CANCELLED, or FAILED |
Coroutine | Qualified name of the coroutine function |
Stack | The coroutine's cr_await chain showing where it is suspended |
If no active coroutines are found:
No active coroutines/async tasks found.
Note: Coroutines are only visible when an event loop is running.
flight_profiler <pid> --cmd "stack" --no-color
Output — each thread shows its name, hex TID, and Python call stack (most recent call first):
(cpu-worker) 0x0000000170da3000 (most recent call first):
File "stack_demo_script.py", line 28 in cpu_worker
File "/Users/zy/miniforge3/envs/py39/lib/python3.9/threading.py", line 888 in run
File "/Users/zy/miniforge3/envs/py39/lib/python3.9/threading.py", line 950 in _bootstrap_inner
File "/Users/zy/miniforge3/envs/py39/lib/python3.9/threading.py", line 908 in _bootstrap
(lock-holder) 0x000000016fd97000 (most recent call first):
File "stack_demo_script.py", line 20 in lock_holder
File "/Users/zy/miniforge3/envs/py39/lib/python3.9/threading.py", line 888 in run
...
(io-worker) 0x000000016ed8b000 (most recent call first):
File "stack_demo_script.py", line 13 in io_worker
File "/Users/zy/miniforge3/envs/py39/lib/python3.9/threading.py", line 888 in run
...
(async-loop) 0x0000000171daf000 (most recent call first):
File "/Users/zy/miniforge3/envs/py39/lib/python3.9/selectors.py", line 562 in select
File "/Users/zy/miniforge3/envs/py39/lib/python3.9/asyncio/base_events.py", line 1854 in _run_once
File "/Users/zy/miniforge3/envs/py39/lib/python3.9/asyncio/base_events.py", line 596 in run_forever
...
File "stack_demo_script.py", line 57 in start_async_thread
...
(MainThread) 0x0000000207ede240 (most recent call first):
File "stack_demo_script.py", line 74 in <module>
Reading this output:
(cpu-worker) — currently at cpu_worker line 28, doing computation(lock-holder) — at lock_holder line 20, sleeping while holding a lock(io-worker) — at io_worker line 13, sleeping in I/O wait(async-loop) — the event loop thread, blocked in selectors.select (normal for async — use -a to see coroutine details)(MainThread) — main thread at line 74, the while True: time.sleep(1) loopflight-profiler-agent and flight-profiler-recv-* threads (PyFlightProfiler's internal threads) — these can be ignoredflight_profiler <pid> --cmd "stack" --no-color
Output — Linux uses pystack, showing GIL status and "most recent call last" order:
Traceback for thread 170938 (python) [Has the GIL] (most recent call last):
* - Unable to merge native stack due to insufficient native information - *
(Python) File "/home/admin/miniforge3/lib/python3.10/threading.py", line 973, in _bootstrap
self._bootstrap_inner()
(Python) File "/home/admin/miniforge3/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
self.run()
(Python) File "/home/admin/miniforge3/lib/python3.10/threading.py", line 953, in run
self._target(*self._args, **self._kwargs)
(Python) File "stack_demo_script.py", line 40, in cpu_worker
total += i
Traceback for thread 170937 (python) [] (most recent call last):
...
(Python) File "stack_demo_script.py", line 32, in lock_holder
time.sleep(5)
Traceback for thread 170936 (python) [] (most recent call last):
...
(Python) File "stack_demo_script.py", line 22, in io_worker
time.sleep(2)
Traceback for thread 170934 (python) [] (most recent call last):
...
(Python) File "stack_demo_script.py", line 97, in main
time.sleep(1)
Reading this output:
170938 (cpu_worker) [Has the GIL] — this thread currently holds the GIL, actively computing170937 (lock_holder) [] — sleeping in time.sleep(5), holding a lock170936 (io_worker) [] — sleeping in time.sleep(2)170934 (main) [] — the main thread, sleeping in time.sleep(1)| macOS | Linux | |
|---|---|---|
| Stack order | Most recent call first | Most recent call last |
| Thread identifier | (thread-name) 0xHEX_TID | thread NUMERIC_TID (python) [GIL status] |
| GIL status | Not shown | [Has the GIL], [Waiting for the GIL], or [] |
| Source code lines | Not shown (file + line number only) | Shown inline |
| Native frames | Not supported | Supported via --native |
--native, Linux only)flight_profiler <pid> --cmd "stack --native" --no-color
Output — mixed Python + C frames, useful for debugging C extensions or GIL contention:
Traceback for thread 170938 (python) [Has the GIL] (most recent call last):
(C) File "???", line 0, in __clone (/usr/lib64/libc-2.32.so)
(C) File "???", line 0, in start_thread (/usr/lib64/libpthread-2.32.so)
(C) File ".../Python/thread_pthread.h", line 248, in pythread_wrapper (python3.10)
(C) File ".../Modules/_threadmodule.c", line 1100, in thread_run (python3.10)
(Python) File "/home/admin/miniforge3/lib/python3.10/threading.py", line 973, in _bootstrap
self._bootstrap_inner()
...
(Python) File "stack_demo_script.py", line 40, in cpu_worker
total += i
Traceback for thread 170937 (python) [] (most recent call last):
(C) File "???", line 0, in __clone (/usr/lib64/libc-2.32.so)
(C) File "???", line 0, in start_thread (/usr/lib64/libpthread-2.32.so)
...
(Python) File "stack_demo_script.py", line 32, in lock_holder
time.sleep(5)
(C) File ".../Modules/timemodule.c", line 370, in time_sleep (python3.10)
(C) File ".../Modules/timemodule.c", line 2076, in pysleep (inlined) (python3.10)
(C) File "???", line 0, in __select (/usr/lib64/libc-2.32.so)
Traceback for thread 170934 (python) [] (most recent call last):
(C) File "???", line 0, in _start (python3.10)
(C) File "???", line 0, in __libc_start_main (/usr/lib64/libc-2.32.so)
(C) File ".../Modules/main.c", line 1094, in Py_BytesMain (python3.10)
...
(Python) File "stack_demo_script.py", line 97, in main
time.sleep(1)
(C) File ".../Modules/timemodule.c", line 370, in time_sleep (python3.10)
(C) File ".../Modules/timemodule.c", line 2076, in pysleep (inlined) (python3.10)
(C) File "???", line 0, in __select (/usr/lib64/libc-2.32.so)
Reading this output:
(C) frames show the native call stack — you can see time.sleep going into CPython's pysleep then into the OS __select syscall[Has the GIL] vs [Waiting for the GIL] helps identify GIL contention-a)flight_profiler <pid> --cmd "stack -a" --no-color
Output — all active asyncio tasks grouped by thread, with their coroutine call chain (same format on both macOS and Linux):
============================================================
Async Coroutine/Task Stacks
============================================================
Thread: async-loop (tid: 0x171daf000)
--------------------------------------------------
Task #1: periodic-heartbeat
State: WAITING
Coroutine: periodic_task
Stack (2 frames):
File "stack_demo_script.py", line 44, in periodic_task
await asyncio.sleep(1)
File ".../asyncio/tasks.py", line 649, in sleep
return await future
Task #2: Task-1
State: WAITING
Coroutine: run_async_loop
Stack (1 frames):
File "stack_demo_script.py", line 53, in run_async_loop
await asyncio.gather(*tasks)
Task #3: process-item-42
State: WAITING
Coroutine: process_item
Stack (2 frames):
File "stack_demo_script.py", line 38, in process_item
await asyncio.sleep(3600)
File ".../asyncio/tasks.py", line 649, in sleep
return await future
Task #4: fetch-api-data
State: WAITING
Coroutine: fetch_data
Stack (2 frames):
File "stack_demo_script.py", line 33, in fetch_data
await asyncio.sleep(3600)
File ".../asyncio/tasks.py", line 649, in sleep
return await future
============================================================
Reading this output:
WAITING — they are suspended at an await pointfetch-api-data and process-item-42 are waiting on asyncio.sleep(3600) — long-running waits, potential indicators of stuck tasksperiodic-heartbeat is waiting on asyncio.sleep(1) — a healthy periodic taskTask-1 (the run_async_loop gather) is waiting for its child tasks to completeasyncio.create_task(name=...) — unnamed tasks show as Task-N-f)flight_profiler <pid> --cmd "stack -f ./stack.log" --no-color
Output:
✓ Write stack to ./stack.log successfully!
The file contains the same thread stack output as the default stack command. Useful when:
ps -p <pid>symbol _Py_DumpTracebackThreads not found-aps -p <pid> -o user=sudo flight_profiler <pid> ...ptrace_scope: cat /proc/sys/kernel/yama/ptrace_scope (should be 0)[Has the GIL] in thread stacks to identify which thread is holding the GIL — if a CPU-bound thread holds it for too long, other threads will show [Waiting for the GIL]-a to see coroutine stacks — thread stacks alone will just show the event loop waiting in epoll_wait/select--native when debugging C extension crashes or hangs — it reveals the C-level call stack beneath Python frames-f before and after a suspected issue for comparison* - Unable to merge native stack due to insufficient native information - * line in default mode is normal — it means native frames are available but not requested (use --native to see them)stack as the first step to locate business code — before running watch, trace, or module, run stack to discover the file paths and module names active in the target process. The stack frames show exactly which files are being executed (e.g., File "myapp/services/order.py", line 42, in process_order), so you can derive the correct module name for subsequent commands--native_Py_DumpTracebackThreads-a): always fetched via server communication on both platforms (requires access to the target's event loop)flight_profiler/plugins/stack/cli_plugin_stack.pyflight_profiler/plugins/stack/stack_parser.pyflight_profiler/plugins/stack/server_plugin_stack.py还没有评价。欢迎分享你的使用感受。
无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。
还没有评论。来写第一条吧。
Prerequisites and connection details for attaching to a live Python process with PyFlightProfiler. Read this skill first before using any other PyFlightProfiler command (watch, trace, stack, perf, etc.).
中文简介正在准备中。当前显示原文说明。
Inspect Python module global field or class static field value in a running Python process. Use this for safe, read-only inspection of global variables, configuration objects, or class-level state.
中文简介正在准备中。当前显示原文说明。
Translate a file path to its Python module name in a running Python process. Use this when you know a file path but need the module name for commands like watch, trace, or reload.
中文简介正在准备中。当前显示原文说明。
Hot-reload a Python function implementation from the latest file content without restarting the process. Use this to apply code fixes live after identifying a bug with watch/trace.
中文简介正在准备中。当前显示原文说明。
Trace execution time of Python method invocations in a live process with call stack visualization. Use this to see a hierarchical call tree showing which sub-calls are slow and where time is spent within a function.
中文简介正在准备中。当前显示原文说明。
Inspect live Python class instances in a running process — find all instances of a class, examine their attributes/state, or invoke methods on them. Also supports forcing GC. Use this when you need to probe object-level runtime state beyond what watch/getglobal can provide.
中文简介正在准备中。当前显示原文说明。