<@ULVA73B9P> Using the Python SDK how do I poll a ...
# ask-marvin
c
@Marvin Using the Python SDK how do I poll a flow run's state to see if it still running, or has reached a terminal state (success, failed, etc).
m
thought for 230.3 seconds
Assuming Prefect 3.x, you’ve got two good options with the Python SDK: 1) Use the built-in waiter (recommended) This will wait until the flow run reaches a terminal state and return the final
FlowRun
.
Copy code
import asyncio
from uuid import UUID

from prefect.flow_runs import wait_for_flow_run
from prefect.client.schemas.objects import StateType
from prefect.exceptions import FlowRunWaitTimeout

async def main(flow_run_id: UUID):
    try:
        flow_run = await wait_for_flow_run(
            flow_run_id,
            poll_interval=2,  # seconds
            timeout=60 * 30,  # 30 minutes
            log_states=True,  # optional: logs transitions
        )
    except FlowRunWaitTimeout:
        print("Timed out waiting for the flow run to finish.")
        return

    final_state = flow_run.state
    print("Final state:", final_state.type, final_state.name)
    if final_state.type == StateType.COMPLETED:
        print("Success!")
    elif final_state.type in {StateType.FAILED, StateType.CANCELLED, StateType.CRASHED}:
        print("Flow run ended in a failure-like terminal state.")

if __name__ == "__main__":
    asyncio.run(main(UUID("YOUR-FLOW-RUN-ID-HERE")))
- Source for `wait_for_flow_run`: prefect/flow_runs.py 2) Manually poll via the client If you want to control the polling loop yourself:
Copy code
import asyncio
from uuid import UUID

from prefect import get_client
from prefect.client.schemas.objects import StateType

TERMINAL = {StateType.COMPLETED, StateType.FAILED, StateType.CANCELLED, StateType.CRASHED}

async def poll_flow_run(flow_run_id: UUID, interval: float = 2.0):
    async with get_client() as client:
        while True:
            flow_run = await client.read_flow_run(flow_run_id)
            state = flow_run.state
            print(f"State: {state.type} ({state.name})")

            if state.type in TERMINAL:
                print("Reached terminal state.")
                return flow_run

            # Optional: check if running explicitly
            if state.type == StateType.RUNNING:
                print("Still running...")

            await asyncio.sleep(interval)

if __name__ == "__main__":
    asyncio.run(poll_flow_run(UUID("YOUR-FLOW-RUN-ID-HERE")))
Useful references - REST API reference for flow run state (helps understand terminal vs non-terminal): Read flow run state (REST) -
wait_for_flow_run
source (shows timeout, poll_interval, logging, return type): prefect/flow_runs.py If you share your exact use case (e.g., needing a sync wrapper, custom logging, or early-exit conditions), I can tailor the snippet.
n
marvin's answer is broadly correct curious why you're asking @Chris Killpack? for example,
run_deployment
waits for you by default, which we could potentially make more clear in docs
c
Hi @Nate. I used create_flow_run_from_deployment to start the run. Given that the jobs / runs we start take a few minutes to complete and will be triggered by end user activity, we want a programatic method to start, poll and cancel runs.
n
nice! one thing i'll put on your radar
Copy code
import asyncio
    from uuid import uuid4

    from prefect import flow
    from prefect.flow_engine import run_flow_async
    from prefect.flow_runs import FlowRunWaiter


    @flow
    async def test_flow():
        await asyncio.sleep(5)
        print("Done!")


    async def main():
        flow_run_id = uuid4()
        asyncio.create_flow(run_flow_async(flow=test_flow, flow_run_id=flow_run_id))

        await FlowRunWaiter.wait_for_flow_run(flow_run_id)
        print("Flow run finished")


    if __name__ == "__main__":
        asyncio.run(main())
this starts a websocket client and blocks until the run reaches a terminal state (ie no need to poll)
Copy code
await FlowRunWaiter.wait_for_flow_run(flow_run_id)
this reminds me, i think we're polling in a place or two we could be using this waiter, PR coming shortly thanks for explaining!
c
Okay thanks Nate, will take a look.