Snapshot and restore Python environments for reproducible notebooks
Project description
snapmyenv 📸
Snapshot and restore Python environments for reproducible notebooks.
snapmyenv is a lightweight, zero-dependency library designed to solve the "it works on my machine" problem for Google Colab and Jupyter Notebooks. It captures your runtime environment—including Python version, OS details, and exact package versions—and embeds it directly into your notebook's metadata.
Share your notebooks with confidence, knowing others can instantly recreate your exact setup with a single command.
🚀 Key Features
- 📸 Full Environment Capture: Records Python version, OS/Platform, and all installed
pippackages. - 📓 Notebook Embedding: Injects dependency snapshots directly into
.ipynbmetadata—making the notebook a self-contained unit. - 🌐 Colab Ready: Includes specific logic to detect and handle Google Colab environments.
- 🛡️ Zero Dependencies: Built using only the Python standard library (
sys,json,subprocess), so installing it never conflicts with your existing environment. - 🔄 Instant Restore: Reinstall the exact package versions required to run a notebook with a single function call.
- ⛑️ Safety First: Includes
dry_runmodes to preview changes before installation.
📦 Installation
!pip install snapmyenv
⚡ Quick Start
1. The "Self-Reproducible" Notebook (Recommended)
The most powerful way to use snapmyenv is to embed the environment inside the notebook itself.
User A (The Author):
import snapmyenv
# 1. Capture the current environment
snapmyenv.capture("stable-v1")
# 2. Embed it into the notebook metadata
snapmyenv.embed("stable-v1", "my_analysis.ipynb")
# Output: ✓ Embedded snapshot 'stable-v1' into my_analysis.ipynb
User B (The Recipient):
import snapmyenv
# Restore the exact environment embedded in the file
snapmyenv.restore_from_nb("my_analysis.ipynb")
# Output:
# Found embedded snapshot in my_analysis.ipynb
# Installing packages...
# ✓ Restoration complete.
🎓 Google Colab Guide
Using snapmyenv in Google Colab requires one extra step: mounting Google Drive. Since Colab instances are temporary, you must save the notebook to your Drive to persist the embedded environment snapshot.
Step 1: Install & Mount Drive
Run this at the top of your notebook to install the library and give it access to save the file.
!pip install snapmyenv
from google.colab import drive
import snapmyenv
# Mount Google Drive so we can save the notebook file
drive.mount('/content/drive')
Step 2: Capture & Embed
Once your analysis is working perfectly, capture the environment and embed it into the notebook file sitting on your Drive.
# 1. Capture the current Colab environment
snapmyenv.capture("final-submission")
# 2. Embed it into your notebook file (adjust the path to match your file)
notebook_path = "/content/drive/MyDrive/Colab Notebooks/my_analysis.ipynb"
snapmyenv.embed("final-submission", notebook_path)
print("✅ Environment saved! You can now share this notebook.")
Step 3: Restoring (For Others)
When someone else opens your notebook, they can restore your exact environment—even if Colab has updated its default packages since you wrote the code.
!pip install snapmyenv
import snapmyenv
from google.colab import drive
drive.mount('/content/drive')
# Restore the environment from the notebook itself
snapmyenv.restore_from_nb("/content/drive/MyDrive/Colab Notebooks/my_analysis.ipynb")
📖 API Reference
capture(name="default", metadata=None) -> dict
Captures the current Python environment state in memory.
- name (
str): Unique identifier for the snapshot. - metadata (
dict): Optional dictionary of extra info (e.g.,{'author': 'Jane', 'experiment': '42'}). - Returns: A dictionary containing the snapshot data.
embed(name="default", notebook_path=None) -> None
Writes a captured snapshot into the JSON metadata of a .ipynb file.
- name (
str): Name of the snapshot to embed. - notebook_path (
str): Path to the notebook. If running in Jupyter, it attempts to auto-detect the path.
restore(name="default", dry_run=False) -> None
Restores an environment from a snapshot currently held in memory.
- name (
str): Name of the snapshot to restore. - dry_run (
bool): IfTrue, prints the list of packages that would be installed without actually installing them.
restore_from_nb(notebook_path=None, dry_run=False) -> None
Reads a snapshot from a notebook file's metadata and restores it.
- notebook_path (
str): Path to the notebook file. - dry_run (
bool): Preview changes without installing.
🔍 What Actually Gets Captured?
Unlike pip freeze, snapmyenv captures the full context required for debugging environment issues:
| Data Point | Description |
|---|---|
| Python Version | e.g., 3.10.12 (Major.Minor.Patch) |
| Platform | e.g., Linux-5.15.0-generic |
| Architecture | e.g., x86_64 |
| Packages | Complete list of pip packages with pinned versions |
| Colab Flag | Boolean flag indicating if the snapshot originated in Colab |
| Timestamp | UTC timestamp of capture |
🛠️ Advanced Usage
Dry Run (Preview Changes)
Before modifying your environment, see exactly what will change:
snapmyenv.restore_from_nb("analysis.ipynb", dry_run=True)
# Output:
# [DRY RUN] Would install:
# numpy==1.24.3
# pandas==2.0.1
Save/Load Snapshots to JSON
If you prefer file-based management over notebook embedding:
import json
import snapmyenv
# Save to JSON
snapshot = snapmyenv.capture("production")
with open("env_snapshot.json", "w") as f:
json.dump(snapshot, f, indent=2)
# Load from JSON
with open("env_snapshot.json", "r") as f:
data = json.load(f)
snapmyenv.restore_from_dict(data)
💻 Development
Setup
Clone the repository and install it in editable mode with development dependencies:
git clone https://github.com/lovnishverma/snapmyenv.git
cd snapmyenv
pip install -e ".[dev]"
Verification Script
The project includes a built-in verification script to check package structure and imports before building. Always run this before submitting a PR:
python verify_package.py
Testing
Run the comprehensive test suite using pytest:
pytest
# Or with coverage report
pytest --cov=snapmyenv --cov-report=html
⚠️ Limitations
- Pip Only: Currently captures standard
pippackages. Does not support Conda-specific packages or system-level binaries (apt/brew). - Virtual Environments: Captures the state of packages (versions), not the virtual environment folder structure itself.
- Cross-Platform: While
snapmyenvrecords the OS, it cannot guarantee that a package compiled for Linux will have a matching version available for Windows.
📄 Changelog
v0.1.4
- Enhanced notebook path detection.
- Improved metadata serialization.
- Added
verify_package.pyfor build validation.
v0.1.0
- Initial release.
- Core capture/restore functionality.
- Google Colab support.
🤝 Contributing
Contributions are welcome! Please:
- Fork the repository.
- Create a feature branch (
git checkout -b feature/amazing-feature). - Commit your changes.
- Run
python verify_package.pyto ensure integrity. - Open a Pull Request.
📄 License
MIT License - see LICENSE file for details.
Made with ❤️ by Lovnish Verma for the Jupyter and Google Colab community
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file snapmyenv-0.1.4.tar.gz.
File metadata
- Download URL: snapmyenv-0.1.4.tar.gz
- Upload date:
- Size: 18.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
88566008852639dbf149fc3c4ec813cec3be72a7152c108af1c5956381ad4c19
|
|
| MD5 |
bfbce55832f54d997bf08019499e1f38
|
|
| BLAKE2b-256 |
1d11db1053e470d4ed1cb6519654f1e8fb9cc9432aa042015e4d884e78874933
|
File details
Details for the file snapmyenv-0.1.4-py3-none-any.whl.
File metadata
- Download URL: snapmyenv-0.1.4-py3-none-any.whl
- Upload date:
- Size: 14.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c20ee881bb766621e0c6c605a9486a4a0876366b86057172cc9b406a1be48de6
|
|
| MD5 |
ee673edb4e0a792a8b58aa35a7ea2739
|
|
| BLAKE2b-256 |
ac925bff530a90ce8aedde5b54fc2075f1db086a5a62733c1709ac73ee332abb
|