KodeKloud 100 Days of MLOps – Day 1: Setting Up a Standardized Python Environment
Step-by-step walkthrough of Day 1 task in KodeKloud 100 Days of MLOps challenge: setting up a virtual environment, installing ML dependencies, and generating requirements.txt on controlplane.
Welcome to Day 1 of the KodeKloud 100 Days of MLOps Challenge!
In today’s challenge, we lay down the foundational infrastructure for xFusionCorp Industries’ data science team. Standardizing development environments is a core MLOps best practice—it guarantees reproducibility, prevents library dependency conflicts across teams, and makes CI/CD pipelines smooth and predictable.
Task Scenario & Requirements
The data science team at xFusionCorp Industries requires a standardized Python virtual environment on the controlplane host for a new machine learning initiative.
Requirements:
- Working Directory: All operations must be performed under
/root/code/. - Virtual Environment: Create a Python virtual environment named
ml-envinside/root/code/. - Packages: Install core ML dependencies:
numpy,pandas,scikit-learn, andmatplotlib. - Reproducibility: Save a complete dependency freeze as
requirements.txtat/root/code/requirements.txt.
Step-by-Step Implementation Guide
Step 1: Navigate to the Project Directory
Actually the terminal in given space is kinda styled and I’m not used to that style and by the look of it working directory was correct but since i don’t want to mess something up I decided to navigate to the given directory since it won’t do any harm.
First, change your directory to the project workspace:
cd /root/code/
Step 2: Create the Virtual Environment
To create the Virtual enviornment we can use 3’s native venv module.If python3-venv is missing, run apt-get update && apt-get install -y python3-venv before running this step.
Use Python 3’s native venv module to isolate dependencies from the global system environment. We name our environment ml-env:
python3 -m venv ml-env
Why we’re creating a venv here Virtual environments encapsulate Python binaries and installed libraries, ensuring isolated package management per project.
Step 3: Activate the Virtual Environment
Activate ml-env so that all subsequent pip operations target this isolated environment rather than system Python:
source /root/code/ml-env/bin/activate
Upon successful activation, your shell prompt will update to show (ml-env).
Step 4: Install Required Machine Learning Libraries
With the environment active, install the necessary libraries (numpy, pandas, scikit-learn, matplotlib):
pip install numpy pandas scikit-learn matplotlib
Step 5: Freeze Environment Dependencies
To make the environment fully reproducible for production deployments and team members, output all exact package versions into a requirements.txt file:
pip freeze > /root/code/requirements.txt
Step 6: Verify and Deactivate
Verify that the files exist in /root/code/ and deactivate the virtual environment when done:
ls -l /root/code
cat /root/code/requirements.txt
deactivate
💻 Full Terminal Session Output
Below is the complete terminal log from executing Day 1’s task on the controlplane host:
root@controlplane ~/code ✖ cd /root/code/
root@controlplane ~/code ➜ python3 -m venv ml-env
root@controlplane ~/code ➜ source /root/code/ml-env/bin/activate
root@controlplane ~/code via 🐍 v3.12.3 (ml-env) ➜ pip install numpy pandas scikit-learn matplotlib
Collecting numpy
Downloading numpy-2.5.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (6.6 kB)
Collecting pandas
Downloading pandas-3.0.5-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.metadata (79 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 79.5/79.5 kB 5.8 MB/s eta 0:00:00
Collecting scikit-learn
Downloading scikit_learn-1.9.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (11 kB)
Collecting matplotlib
Downloading matplotlib-3.11.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (80 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 80.3/80.3 kB 64.7 MB/s eta 0:00:00
Collecting python-dateutil>=2.8.2 (from pandas)
Downloading python_dateutil-2.9.0.post0-py2.py3-none-any.whl.metadata (8.4 kB)
Collecting scipy>=1.10.0 (from scikit-learn)
Downloading scipy-1.18.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (62 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 62.3/62.3 kB 62.4 MB/s eta 0:00:00
Collecting joblib>=1.4.0 (from scikit-learn)
Downloading joblib-1.5.3-py3-none-any.whl.metadata (5.5 kB)
Collecting narwhals>=2.0.1 (from scikit-learn)
Downloading narwhals-2.24.0-py3-none-any.whl.metadata (15 kB)
Collecting threadpoolctl>=3.5.0 (from scikit-learn)
Downloading threadpoolctl-3.6.0-py3-none-any.whl.metadata (13 kB)
Collecting contourpy>=1.0.1 (from matplotlib)
Downloading contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (5.5 kB)
Collecting cycler>=0.10 (from matplotlib)
Downloading cycler-0.12.1-py3-none-any.whl.metadata (3.8 kB)
Collecting fonttools>=4.28.2 (from matplotlib)
Downloading fonttools-4.63.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (118 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 118.7/118.7 kB 81.0 MB/s eta 0:00:00
Collecting kiwisolver>=1.3.1 (from matplotlib)
Downloading kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (5.1 kB)
Collecting packaging>=20.0 (from matplotlib)
Downloading packaging-26.2-py3-none-any.whl.metadata (3.5 kB)
Collecting pillow>=9 (from matplotlib)
Downloading pillow-12.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (9.1 kB)
Collecting pyparsing>=3 (from matplotlib)
Downloading pyparsing-3.3.2-py3-none-any.whl.metadata (5.8 kB)
Collecting six>=1.5 (from python-dateutil>=2.8.2->pandas)
Downloading six-1.17.0-py2.py3-none-any.whl.metadata (1.7 kB)
Downloading numpy-2.5.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (16.7 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 16.7/16.7 MB 97.2 MB/s eta 0:00:00
Downloading pandas-3.0.5-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (11.0 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 11.0/11.0 MB 102.3 MB/s eta 0:00:00
Downloading scikit_learn-1.9.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (9.1 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 9.1/9.1 MB 106.7 MB/s eta 0:00:00
Downloading matplotlib-3.11.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (10.0 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 10.0/10.0 MB 103.8 MB/s eta 0:00:00
Downloading contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (362 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 362.6/362.6 kB 186.5 MB/s eta 0:00:00
Downloading cycler-0.12.1-py3-none-any.whl (8.3 kB)
Downloading fonttools-4.63.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (5.0 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5.0/5.0 MB 90.8 MB/s eta 0:00:00
Downloading joblib-1.5.3-py3-none-any.whl (309 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 309.1/309.1 kB 104.5 MB/s eta 0:00:00
Downloading kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.5 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.5/1.5 MB 111.2 MB/s eta 0:00:00
Downloading narwhals-2.24.0-py3-none-any.whl (461 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 461.0/461.0 kB 114.5 MB/s eta 0:00:00
Downloading packaging-26.2-py3-none-any.whl (100 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100.2/100.2 kB 91.3 MB/s eta 0:00:00
Downloading pillow-12.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (6.9 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 6.9/6.9 MB 107.5 MB/s eta 0:00:00
Downloading pyparsing-3.3.2-py3-none-any.whl (122 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 122.8/122.8 kB 110.0 MB/s eta 0:00:00
Downloading python_dateutil-2.9.0.post0-py2.py3-none-any.whl (229 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 229.9/229.9 kB 124.2 MB/s eta 0:00:00
Downloading scipy-1.18.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (35.3 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 35.3/35.3 MB 88.2 MB/s eta 0:00:00
Downloading threadpoolctl-3.6.0-py3-none-any.whl (18 kB)
Downloading six-1.17.0-py2.py3-none-any.whl (11 kB)
Installing collected packages: threadpoolctl, six, pyparsing, pillow, packaging, numpy, narwhals, kiwisolver, joblib, fonttools, cycler, scipy, python-dateutil, contourpy, scikit-learn, pandas, matplotlib
Successfully installed contourpy-1.3.3 cycler-0.12.1 fonttools-4.63.0 joblib-1.5.3 kiwisolver-1.5.0 matplotlib-3.11.1 narwhals-2.24.0 numpy-2.5.1 packaging-26.2 pandas-3.0.5 pillow-12.3.0 pyparsing-3.3.2 python-dateutil-2.9.0.post0 scikit-learn-1.9.0 scipy-1.18.0 six-1.17.0 threadpoolctl-3.6.0
root@controlplane ~/code via 🐍 v3.12.3 (ml-env) ➜ pip freeze > /root/code/requirements.txt
root@controlplane ~/code via 🐍 v3.12.3 (ml-env) ➜ ls -l /root/code
total 12
-rw-r--r-- 1 root root 725 Jul 26 07:22 README.md
drwxr-xr-x 6 root root 4096 Jul 26 08:05 ml-env
-rw-r--r-- 1 root root 289 Jul 26 08:06 requirements.txt
root@controlplane ~/code via 🐍 v3.12.3 (ml-env) ➜ cat /root/code/requirements.txt
contourpy==1.3.3
cycler==0.12.1
fonttools==4.63.0
joblib==1.5.3
kiwisolver==1.5.0
matplotlib==3.11.1
narwhals==2.24.0
numpy==2.5.1
packaging==26.2
pandas==3.0.5
pillow==12.3.0
pyparsing==3.3.2
python-dateutil==2.9.0.post0
scikit-learn==1.9.0
scipy==1.18.0
six==1.17.0
threadpoolctl==3.6.0
root@controlplane ~/code via 🐍 v3.12.3 (ml-env) ➜ deactivate
root@controlplane ~/code via 🐍 v3.12.3 ➜
What to learn here.
- Isolation Matters: Always run
python3 -m venv <env_name>to create isolated environments for separate projects, preventing package collision. - Lock Down Dependencies: Running
pip freeze > requirements.txtcaptures explicit version numbers (e.g.,numpy==2.5.1,pandas==3.0.5), ensuring identical environments across staging and production. - Transitive Dependencies: Notice how installing 4 top-level packages (
numpy,pandas,scikit-learn,matplotlib) pulled in transitive dependencies likescipy,joblib,kiwisolver, andpillow.pip freezerecords all of them for 100% fidelity.
Stay tuned for Day 2 of the 100 Days of MLOps challenge!