Here’s a simple flow using different versions of pandas in different steps:
simplecondaflow.py
from metaflow import FlowSpec, step, condaclass CondaTestFlow(FlowSpec): @conda(libraries={"pandas": "1.4.0"}, python=">=3.8,<3.9") @step def start(self): import pandas as pd assert pd.__version__ == "1.4.0" print("I am in start and Pandas version is %s" % pd.__version__) self.next(self.end) @conda(libraries={"pandas": "1.5.0"}, python=">=3.8,<3.9") @step def end(self): import pandas as pd assert pd.__version__ == "1.5.0" print("I am in end and Pandas version is %s" % pd.__version__)if __name__ == "__main__": CondaTestFlow()
You must use --environment=conda when running flows that use Conda decorators.
Run the flow:
python simplecondaflow.py --environment=conda run
Output:
Workflow starting (run-id 142), see it in the UI at https://mfui.net/CondaTestFlow/142 Using existing Conda environment 42a4ed94b63f12e1fe9dd29de21bf9ec6e271b1c (a3b104c4ce2215351a2b94076ef7827de3ad890a) [142/start/145426383 (pid 21786)] Task is starting. [142/start/145426383 (pid 21786)] I am in start and Pandas version is 1.4.0 [142/start/145426383 (pid 21786)] Task finished successfully. Using existing Conda environment 3e07a415e7766b8ed359f00e5f48e35ec79ac056 (41a06733cd332951fa100475c3a05c6916272899) [142/end/145426398 (pid 21837)] Task is starting. [142/end/145426398 (pid 21837)] I am in end and Pandas version is 1.5.0 [142/end/145426398 (pid 21837)] Task finished successfully. Done! See the run in the UI at https://mfui.net/CondaTestFlow/142
You can also use pure PyPI packages with the @pypi decorator:
simplecondaflow-pypi.py
from metaflow import FlowSpec, step, pypiclass CondaTestFlowPypi(FlowSpec): @pypi(packages={"pandas": "1.4.0"}, python=">=3.8,<3.9") @step def start(self): import pandas as pd assert pd.__version__ == "1.4.0" print("I am in start and Pandas version is %s" % pd.__version__) self.next(self.end) @pypi(packages={"pandas": "1.5.0"}, python=">=3.8,<3.9") @step def end(self): import pandas as pd assert pd.__version__ == "1.5.0" print("I am in end and Pandas version is %s" % pd.__version__)if __name__ == "__main__": CondaTestFlowPypi()
python simplecondaflow-pypi.py --environment=conda run
Use flow-level decorators to specify common dependencies for all steps:
from metaflow import FlowSpec, step, conda, conda_base@conda_base(libraries={'numpy':'1.21.5'}, python='>3.8,<3.9')class CondaTestFlow(FlowSpec): @step def a(self): import numpy as np print(f"Step A: numpy {np.__version__}") self.next(self.b) @conda(libraries={'numpy':'1.21.6'}) @step def b(self): import numpy as np print(f"Step B: numpy {np.__version__}") self.next(self.c) @conda(disabled=True) @step def c(self): # This step runs outside the conda environment print("Step C: using system environment")if __name__ == "__main__": CondaTestFlow()
In this example:
Step A executes with numpy==1.21.5 and python>3.8,<3.9 (from @conda_base)
Step B executes with numpy==1.21.6 and python>3.8,<3.9 (overrides numpy)
Step C executes outside the conda environment (system environment)
Step-level decorators override flow-level decorators. Use this pattern to set common dependencies at the flow level and override them for specific steps.
By default, Metaflow will reuse previously resolved environments. Use --force only when you need to pick up new package versions or resolve for a new architecture.