<@ULVA73B9P> can we run powershell scripts with pr...
# ask-marvin
h
@Marvin can we run powershell scripts with prefect shell utility in python?
m
thought for 293.8 seconds
Yes. In Prefect 3.x you can run PowerShell from Python in a few ways. Quick options - Use Prefect’s shell utility flow:
prefect.cli.shell.run_shell_process
(logs output, raises on non‑zero, supports env/cwd via
popen_kwargs
) - If you need to capture stdout/stderr as return values inside your flow code, use Python’s
subprocess
in a
@task
- For deployment build/pull steps (prefect.yaml), use the
run_shell_script
step which returns stdout/stderr Examples 1) Run a .ps1 file from a flow with Prefect’s shell utility (logs output)
Copy code
from prefect import flow
from prefect.cli.shell import run_shell_process
import os

@flow
def run_ps():
    run_shell_process(
        command='powershell -NoProfile -ExecutionPolicy Bypass -File ".\\script.ps1" -Arg1 value',
        log_output=True,
        stream_stdout=True,  # stream live stdout to Prefect logs
        popen_kwargs={
            "cwd": r"C:\path\to\dir",
            "env": {**os.environ, "MY_VAR": "123"},
        },
    )

if __name__ == "__main__":
    run_ps()
Notes: -
run_shell_process
does not return stdout/stderr; it logs them. It raises on non-zero exit (Prefect
FailedRun
). -
popen_kwargs
supports standard
subprocess.Popen
args like
env
and
cwd
. 2) Capture output programmatically in a task
Copy code
from prefect import flow, task
import subprocess, os

@task
def run_powershell_capture(cmd: str):
    r = subprocess.run(
        cmd,
        shell=True,          # ok on Windows to use PowerShell/cmd pipelines
        text=True,
        capture_output=True,
        cwd=r"C:\path\to\dir",
        env={**os.environ, "MY_VAR":"123"},
    )
    if r.returncode != 0:
        raise RuntimeError(f"PowerShell failed: {r.stderr}")
    return r.stdout

@flow
def my_flow():
    out = run_powershell_capture('powershell -NoProfile -Command "Get-Date"')
    print(out)

if __name__ == "__main__":
    my_flow()
3) If you’re configuring deployments (prefect.yaml), and want stdout/stderr back
Copy code
build:
  - prefect.deployments.steps.run_shell_script:
      id: setup
      script: powershell -NoProfile -ExecutionPolicy Bypass -Command "Write-Output 'Hello from PS'"
      directory: C:\path\to\dir
      env:
        MY_VAR: "123"
      stream_output: true
- This step returns both
stdout
and
stderr
that can be referenced by subsequent steps (e.g.,
{{ setup.stdout }}
) and fails on non-zero exit. Gotchas and tips - On Windows, the default shell is cmd.exe; explicitly invoke PowerShell:
powershell ...
or
pwsh ...
(for PowerShell 7+). If you need PS7 features cross‑platform, use
pwsh
. - Execution policy can block .ps1 files. Common fixes:
-ExecutionPolicy Bypass
or set it per-process:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force
. - For pipelines/redirection, keep
shell=True
(Prefect’s
run_shell_process
already does this). With
subprocess.run
, specify it yourself. - Encoding: if you see odd characters, set output encoding in PowerShell:
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
. If you can share whether you need to capture stdout/stderr in Python and whether you’re on Windows PowerShell 5.1 or PowerShell 7 (
pwsh
), I can tailor the snippet further.