A reusable package for executing Python code in Docker containers and extracting charts/images
Project description
Codibox - Safe Code Execution Package
A reusable Python package for executing Python code in Docker containers or on the host machine, with automatic chart/image extraction and result processing.
๐ฏ Features
- Dual Backend Support: Choose between Docker (secure, isolated) or Host (fast, direct execution)
- Automatic Image Extraction: Automatically finds and extracts charts/images from code execution
- Markdown Processing: Converts notebook output to markdown with embedded images
- CSV File Extraction: Automatically extracts generated CSV/Excel files
- Dependency Management: Auto-installs required packages for host mode
- Error Handling: Comprehensive error handling with fallbacks
- Backward Compatible:
DockerCodeExecutoralias maintained for existing code
๐ฆ Installation
From PyPI (Recommended)
pip install codibox
From Source
# Clone the repository
git clone https://github.com/otmane-elbourki/codibox.git
cd codibox
# Install in editable mode
pip install -e .
Development Installation
pip install -e ".[dev]"
๐ Quick Start
Docker Backend (Default - Secure)
from codibox import CodeExecutor
# Initialize executor with Docker backend
executor = CodeExecutor(backend="docker", container_name="sandbox")
# Execute code
result = executor.execute(
code="""
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.figure(figsize=(10, 6))
plt.plot(x, y, label='sin(x)')
plt.title('Sine Wave')
plt.savefig('temp_code_files/chart.png')
plt.close()
"""
)
# Check results
if result.success:
print(f"โ
Success! Generated {len(result.images)} images")
for img in result.images:
print(f" ๐ {img}")
print(f"๐ Markdown: {result.markdown[:100]}...")
else:
print(f"โ Failed: {result.stderr}")
Host Backend (Fast - Direct Execution)
from codibox import CodeExecutor
# Initialize executor with Host backend (fast mode)
executor = CodeExecutor(backend="host", auto_install_deps=True)
# Execute code (same API as Docker backend)
result = executor.execute(
code="""
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.cos(x)
plt.figure(figsize=(10, 6))
plt.plot(x, y)
plt.title('Cosine Wave')
plt.savefig('temp_code_files/cosine.png')
plt.close()
"""
)
# Results work the same way
print(f"Images: {result.images}")
print(f"Success: {result.success}")
Backward Compatibility
# Old code still works!
from codibox import DockerCodeExecutor
executor = DockerCodeExecutor(container_name="sandbox")
result = executor.execute(code="...")
๐ API Reference
CodeExecutor
Main class for executing Python code with dual backend support.
Initialization
CodeExecutor(
backend: str = "docker", # "docker" or "host"
container_name: str = "sandbox", # Docker container name (docker only)
host_temp_dir: str = "/tmp", # Temporary directory on host
image_output_dir: str = "temp_code_files", # Directory for images
timeout: Optional[int] = 300, # Execution timeout (seconds)
cleanup_on_error: bool = True, # Cleanup on error
auto_setup: bool = False, # Auto-setup Docker container (docker only)
auto_install_deps: bool = True, # Auto-install dependencies (host only)
)
Methods
execute(code, input_files=None, working_dir=None) -> ExecutionResult
Execute Python code and return results.
Parameters:
code(str): Python code to executeinput_files(List[str], optional): Input files to copy to container/hostworking_dir(str, optional): Working directory (default:/home/sandboxuserfor Docker, temp dir for Host)
Returns: ExecutionResult object
check_container() -> bool
Check if Docker container is running (Docker backend only).
get_container_status() -> Dict[str, Any]
Get detailed status of Docker container (Docker backend only).
Returns: Dictionary with exists, running, status, image
setup_container(image_name="python_sandbox:latest", force_rebuild=False) -> bool
Set up Docker container by building image and starting container (Docker backend only).
ExecutionResult
Result object returned by execute() method.
@dataclass
class ExecutionResult:
# Raw outputs
markdown: str # Raw markdown from notebook execution
success: bool # Whether execution succeeded
images: List[str] # List of image file paths on host
csv_files: List[str] # List of generated CSV/Excel files
stdout: Optional[str] # Standard output
stderr: Optional[str] # Standard error
execution_time: Optional[float] # Execution time in seconds
# Processed outputs
markdown_processed: Optional[str] # Markdown with resolved image paths
markdown_with_images: Optional[str] # Markdown with base64-embedded images
image_map: Optional[Dict[str, str]] # Mapping: markdown_ref -> actual_path
ImageProcessor
Utility class for processing images from execution results.
from codibox import ImageProcessor
processor = ImageProcessor(image_base_dir="/tmp/temp_code_files")
# Find all images
images = processor.find_images()
# Process markdown to embed images
processed_markdown = processor.process_markdown(result.markdown)
# Get HTML for all images
html = processor.get_all_images_html()
๐ง Configuration Examples
Docker Backend Setup
from codibox import CodeExecutor
# Basic setup
executor = CodeExecutor(backend="docker", container_name="sandbox")
# Auto-setup container if not running
executor = CodeExecutor(
backend="docker",
container_name="sandbox",
auto_setup=True # Automatically builds/starts container
)
# Manual container setup
executor = CodeExecutor(backend="docker")
if not executor.check_container():
executor.setup_container()
# Custom timeout
executor = CodeExecutor(backend="docker", timeout=600) # 10 minutes
Host Backend Setup
from codibox import CodeExecutor
# Basic setup (auto-installs dependencies)
executor = CodeExecutor(backend="host")
# Disable auto-installation
executor = CodeExecutor(
backend="host",
auto_install_deps=False # You must install dependencies manually
)
# Custom temp directory
executor = CodeExecutor(
backend="host",
host_temp_dir="/custom/tmp"
)
๐ Usage Examples
With Input Files
executor = CodeExecutor(backend="docker")
result = executor.execute(
code="""
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('data.csv')
plt.hist(df['age'], bins=20, edgecolor='black')
plt.title('Age Distribution')
plt.savefig('temp_code_files/age_dist.png')
plt.close()
""",
input_files=["datasets/customer_data.csv"]
)
print(f"Generated {len(result.images)} charts")
print(f"CSV files: {result.csv_files}")
Processing Images
from codibox import CodeExecutor, ImageProcessor
executor = CodeExecutor(backend="host")
result = executor.execute(code="...")
# Process images
processor = ImageProcessor()
markdown_with_images = processor.process_markdown(result.markdown)
# Or get all images as HTML
images_html = processor.get_all_images_html()
print(images_html)
Accessing Processed Results
result = executor.execute(code="...")
# Raw markdown (with image references)
print(result.markdown)
# Processed markdown (with resolved paths)
if result.markdown_processed:
print(result.markdown_processed)
# Markdown with embedded base64 images
if result.markdown_with_images:
print(result.markdown_with_images)
# Image mapping
if result.image_map:
for ref, path in result.image_map.items():
print(f"{ref} -> {path}")
๐ณ Docker Backend Details
Container Setup
The Docker backend requires a running container. You can:
-
Auto-setup (recommended for development):
executor = CodeExecutor(backend="docker", auto_setup=True)
-
Manual setup:
executor = CodeExecutor(backend="docker") executor.setup_container()
-
Use existing container:
executor = CodeExecutor(backend="docker", container_name="my_container")
Container Requirements
The container should have:
- Python 3.10+
- Required packages:
pandas,numpy,matplotlib,jupyter,nbconvert,ipynb-py-convert - Working directory:
/home/sandboxuser(or/tmp)
The package includes a Dockerfile and requirements.txt in the docker/ directory for building a compatible container.
๐ป Host Backend Details
Automatic Dependency Management
The Host backend automatically checks and installs required packages:
matplotlibpandasnumpyjupyternbconvertipynb-py-convert
Python 3.13 Compatibility
The Host backend automatically handles Python 3.13 SQLite issues by falling back to direct Python execution when Jupyter fails.
Security Considerations
โ ๏ธ Important: The Host backend runs code with user permissions and has no isolation. Use Docker backend for untrusted code.
๐ Backend Comparison
| Feature | Docker Backend | Host Backend |
|---|---|---|
| Security | โ Isolated, secure | โ ๏ธ Runs with user permissions |
| Speed | ~2-5 seconds | ~0.5-2 seconds |
| Setup | Requires Docker | No setup needed |
| Dependencies | Pre-installed in container | Auto-installed on first use |
| Isolation | โ Full isolation | โ No isolation |
| Network | โ No network access | โ Full network access |
| Use Case | Production, untrusted code | Development, trusted code |
๐ Examples
See the examples/ directory for complete usage examples:
basic_usage.py- Simple code execution examplesai_analyst/- Complete Streamlit dashboard applicationREADME.md- Detailed examples documentation
Running Examples
# Setup Docker container (if using Docker backend)
cd examples
./setup_example.sh
# Run basic examples
python basic_usage.py
# Run Streamlit app
cd ai_analyst
streamlit run streamlit_chart_generator.py
๐งช Testing
Run the test suite to verify both backends:
python3 test/test_both_backends.py
This will test:
- Docker backend execution
- Host backend execution
- Image generation and extraction
- Markdown processing
- Error handling
๐ Advanced Usage
Custom Working Directory
# Docker backend
result = executor.execute(
code="...",
working_dir="/custom/path"
)
# Host backend
executor = CodeExecutor(
backend="host",
host_temp_dir="/custom/tmp"
)
Error Handling
result = executor.execute(code="...")
if not result.success:
print(f"Execution failed: {result.stderr}")
print(f"Execution time: {result.execution_time}s")
else:
print(f"Success! Generated {len(result.images)} images")
Container Management
executor = CodeExecutor(backend="docker")
# Check container status
status = executor.get_container_status()
print(f"Container exists: {status['exists']}")
print(f"Container running: {status['running']}")
# Setup container
if not executor.check_container():
executor.setup_container(force_rebuild=True)
๐ Troubleshooting
Docker Backend Issues
Container not found:
# Auto-setup container
executor = CodeExecutor(backend="docker", auto_setup=True)
# Or manually setup
executor.setup_container()
Images not extracted:
- Ensure code saves images to
temp_code_files/directory - Check container working directory matches executor configuration
Host Backend Issues
Dependencies not installed:
# Enable auto-installation
executor = CodeExecutor(backend="host", auto_install_deps=True)
Python 3.13 SQLite errors:
- Automatically handled with fallback to direct Python execution
- No action needed
Images not found:
- Ensure
temp_code_files/directory exists (created automatically) - Check image paths in code match
image_output_dirsetting
๐ฆ Package Structure
codibox/
โโโ __init__.py # Package initialization
โโโ executor.py # CodeExecutor class
โโโ image_processor.py # Image processing utilities
โโโ types.py # Type definitions
โโโ docker/
โ โโโ Dockerfile # Docker image definition
โ โโโ requirements.txt # Docker dependencies
โโโ test/
โ โโโ test_both_backends.py # Test script
โโโ examples/ # Usage examples
๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ค Author
Otmane El Bourki
- Email: otmane.elbourki@gmail.com
- GitHub: @otmane-elbourki
๐ Links
- PyPI: https://pypi.org/project/codibox/
- GitHub: https://github.com/otmane-elbourki/codibox
- Issues: https://github.com/otmane-elbourki/codibox/issues
โญ Features Summary
- โ Dual backend support (Docker & Host)
- โ Automatic image/chart extraction
- โ Markdown processing with embedded images
- โ CSV file extraction
- โ Automatic dependency management
- โ Python 3.13 compatibility
- โ Comprehensive error handling
- โ Backward compatibility
- โ Well-documented API
- โ Production ready
Version: 1.0.1
Status: โ
Production Ready
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 codibox-1.0.2.tar.gz.
File metadata
- Download URL: codibox-1.0.2.tar.gz
- Upload date:
- Size: 19.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5b4e0583cd2a82d8b1fb97387535da1a08a954928b587deff5b52b09a0b1e7b
|
|
| MD5 |
495a75e06f8c221de0c8b0158a8f1034
|
|
| BLAKE2b-256 |
6a1910315478595b3b6762297c5c7239864a5963ff475a5569ef38709bb41324
|
File details
Details for the file codibox-1.0.2-py3-none-any.whl.
File metadata
- Download URL: codibox-1.0.2-py3-none-any.whl
- Upload date:
- Size: 17.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6e1dc3a98985bba258f32080996b78715b6b2c7134981c5a0738a0f01147f95
|
|
| MD5 |
aed7ca298fac2ebdc4325147e2056b6a
|
|
| BLAKE2b-256 |
dad1a631f4b503909d3a84a0b0fcc9720b5541401b9696fbd09b5847489670d3
|