<@ULVA73B9P> Having a deployment script like: ``` ...
# ask-marvin
k
@Marvin Having a deployment script like:
Copy code
if __name__ == "__main__":
    deployment_id = my-flow.deploy(
        name="some-flow",
        work_pool_name="workpool",
        image="<my:image>",
        build=False,
        push=False,
        version="local",
        tags=[],
        description=None,
        entrypoint_type=EntrypointType.MODULE_PATH,
        job_variables={
            ...
        },
    )
    print(f"Created/updated deployment: {deployment_id}")
How can I avoid to have
my-flow
imported. What I actually want is to say: make a deployment with entrypoint "some.package.as.string.file.py::flow_function".
m
thought for 366.1 seconds
You don’t need to import the flow object. In Prefect 3.x you can load a flow from an entrypoint string and then deploy it. Two valid entrypoint styles: - Module path (no colon):
some.package.as.string.file.flow_function
- File path (single colon):
some/package/as/string/file.py:flow_function
Note: Double-colon
::
is not supported. Example using Flow.from_source and deploying (no direct import of
my_flow
):
Copy code
from prefect.flows import Flow
from prefect.types.entrypoint import EntrypointType

if __name__ == "__main__":
    # Pick ONE of the two styles:

    # 1) Module path (requires the package to be importable from the project root)
    entrypoint = "some.package.as.string.file.flow_function"
    entrypoint_type = EntrypointType.MODULE_PATH

    # 2) File path (single colon)
    # entrypoint = "some/package/as/string/file.py:flow_function"
    # entrypoint_type = EntrypointType.FILE_PATH

    # 'source' can be "." (local project root) or a remote repo URL, e.g. "<https://github.com/org/repo>"
    flow_ref = Flow.from_source(
        source=".",
        entrypoint=entrypoint,
    )

    deployment_id = flow_ref.deploy(
        name="some-flow",
        work_pool_name="workpool",
        image="<my:image>",
        build=False,
        push=False,
        version="local",
        tags=[],
        description=None,
        entrypoint_type=entrypoint_type,  # optional — Prefect auto-detects based on presence of ':'
        job_variables={
            # ...
        },
    )
    print(f"Created/updated deployment: {deployment_id}")
A few tips: - Use MODULE_PATH if your package is importable (i.e., project root on PYTHONPATH or installed). Otherwise, prefer FILE_PATH with a single colon. - You can omit
entrypoint_type
and let Prefect auto-detect it from the string. - For remote sources (e.g., GitHub), pass the repo URL to
source
, e.g.
source="<https://github.com/owner/repo>"
. Docs for reference: - Flow.from_source API - Deploy via Python - EntrypointType Quick question to tailor this: where does your flow code live (local package vs raw file path vs Git repo)? That will determine the best
source
and entrypoint style.
k
@Marvin I don't understand the use of
flow_ref
. This can be anything, it actaully doesn't matter, since we pass the real entrypoint anyway?
m
thought for 31.3 seconds
Great question — the variable name
flow_ref
isn’t special. It’s just the Flow object you get back from Flow.from_source so you can call .deploy() on it. You can skip naming it and just chain the calls. What matters is: - Flow.from_source(source, entrypoint) creates a Flow object that references your code by entrypoint string (it doesn’t need to import your flow at deploy time). - .deploy() is an instance method, so you need that Flow object (even if you don’t store it in a variable). So you can write it inline like this:
Copy code
from prefect.flows import Flow
from prefect.types.entrypoint import EntrypointType

if __name__ == "__main__":
    deployment_id = Flow.from_source(
        source=".",  # or a repo URL like "<https://github.com/org/repo>"
        entrypoint="some.package.as.string.file.flow_function",  # module path
    ).deploy(
        name="some-flow",
        work_pool_name="workpool",
        image="<my:image>",
        build=False,
        push=False,
        version="local",
        tags=[],
        description=None,
        # optional — Prefect auto-detects from the string; include if you want to be explicit:
        entrypoint_type=EntrypointType.MODULE_PATH,
        job_variables={
            # ...
        },
    )
    print(f"Created/updated deployment: {deployment_id}")
Entrypoint formatting reminder: - Module path (no .py file, no colon):
some.package.as.string.file.flow_function
- File path (single colon):
some/package/as/string/file.py:flow_function
- Double-colon
::
is not supported. In short: the object returned by Flow.from_source isn’t arbitrary, but you don’t need to name it — just chain .deploy(). The actual import of your flow code happens later by the worker at run time using the entrypoint you provided.
k
@Marvin I still don't get it: I have a docker container with all the code. If I know the entrypoint (by string), that should be enough. But now, we still have to generate somehow the entrypoint to make the deployment, which doesn't make any sense. Even if I make a dummy flow and use that one to make deployment, it still works. So that dummy flow doesn't do anything, it just holds some kind of way to be able to run the deploy method, that's all. I'd prefer to than just call deploy, without having a reference in what form or shape to a method or object.
m
thought for 230.0 seconds
You’re right — if you already know the entrypoint string and your Docker image contains all the code, you don’t need to import or construct a Flow at all. You can create a deployment directly, without any “dummy flow,” by instantiating a RunnerDeployment and calling the top-level deploy function. Pattern A: Code is baked into your image (no storage needed) - Put your prebuilt image in job_variables so the worker uses it at runtime - Set build=False and push=False to skip image build/push
Copy code
from prefect.deployments.runner import RunnerDeployment
from prefect.deployments import deploy

deployment = RunnerDeployment(
    name="some-flow",
    entrypoint="some.package.as.string.file.flow_function",  # module path; no colon
    work_pool_name="workpool",
    job_variables={
        # For Docker work pools:
        "image": "<my:image>",
        # Add any other worker-specific fields as needed
    },
    version="local",
    tags=[],
    description=None,
)

deployment_id = deploy(deployment, build=False, push=False)[0]
print(f"Created/updated deployment: {deployment_id}")
Notes: - Module path uses dots (e.g.,
pkg.subpkg.module.flow_func
), not double-colons. - If you prefer file path style, use
path/to/file.py:flow_function
(single colon). Pattern B: Let Prefect pull your code from source (if not baked into the image)
Copy code
from prefect.runner.storage import create_storage_from_source
from prefect.deployments.runner import RunnerDeployment
from prefect.deployments import deploy

storage = create_storage_from_source(".")  # or "<https://github.com/org/repo>"
deployment = RunnerDeployment.from_storage(
    storage=storage,
    entrypoint="path/to/file.py:flow_function",  # or module path
    name="some-flow",
    work_pool_name="workpool",
    job_variables={"image": "<my:image>"},
    version="local",
)

deployment_id = deploy(deployment, build=False, push=False)[0]
print(f"Created/updated deployment: {deployment_id}")
Why this works: - The Flow object isn’t required. RunnerDeployment holds the metadata (name, entrypoint, storage, work pool, job vars) Prefect needs to register the deployment. The actual import of your code happens later, inside the worker, using the entrypoint string and your image. Docs for reference: - Deploy via Python - Flow.from_source (not required in your case, but related) - Runner storage options Quick follow-up: Which work pool are you using (Docker or Kubernetes)? The
job_variables
schema differs slightly per pool, and I can tailor the example for your setup.
k
nice, thx @Marvin
m
thought for 8.5 seconds
You’re welcome! If you tell me which work pool you’re using (Docker or Kubernetes), I can share a ready-to-paste
job_variables
snippet tailored to it.