<@ULVA73B9P>: Do prefect.variable.Variable.get() c...
# marvin-ai
c
@Marvin: Do prefect.variable.Variable.get() calls have to be made within a Prefect context, like a flow or task? (Prefect v2.20)
m
thought for 70.0 seconds
No. In Prefect 2.20,
Variable.get()
can be called from ordinary Python code outside a flow or task:
Copy code
from prefect.variables import Variable

value = Variable.get("my_variable")  # synchronous code
In async code:
Copy code
value = await Variable.get("my_variable")
It uses the configured Prefect API/profile; a flow or task context is not required.
c
@Marvin: When I try to deploy a flow, it complains that Blocks and Variables aren't awaiting, but I want them to use synchronous methods, not async ones... """ ENV = PrefectVariable.get("env").value # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'coroutine' object has no attribute 'value' An exception occurred. sys1 RuntimeWarning: coroutine 'Block.load' was never awaited RuntimeWarning: Enable tracemalloc to get the object allocation traceback sys1 RuntimeWarning: coroutine 'Variable.get' was never awaited RuntimeWarning: Enable tracemalloc to get the object allocation traceback """
m
thought for 205.2 seconds
This happens because
prefect deploy
imports your flow module while its own async event loop is running. In Prefect 2.20,
Variable.get()
and
Block.load()
are “sync-compatible”; when they detect that async context, they return coroutines—even if your flow itself is synchronous. Also,
Variable.get()
returns the stored value directly, so it should not have
.value
. Recommended: avoid loading Variables or Blocks at module import time. Load them inside the synchronous flow/task:
Copy code
from prefect import flow
from prefect.variables import Variable
from prefect.blocks.system import Secret

@flow
def my_flow():
    env = Variable.get("env")
    secret = Secret.load("my-secret").get()
If they absolutely must be module-level, force Prefect 2.20's synchronous path:
Copy code
ENV = Variable.get("env", _sync=True)
BLOCK = MyBlock.load("my-block", _sync=True)
_sync=True
is an internal compatibility argument, so moving the calls into the flow is more robust. This exact module-import behavior is tracked in Prefect issue #15086.