Skip to main content

A reusable package for executing Python code in Docker containers and extracting charts/images

Project description

Codibox - Safe Code Execution Package

Python 3.10+ License: MIT

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: DockerCodeExecutor alias 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 execute
  • input_files (List[str], optional): Input files to copy to container/host
  • working_dir (str, optional): Working directory (default: /home/sandboxuser for 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:

  1. Auto-setup (recommended for development):

    executor = CodeExecutor(backend="docker", auto_setup=True)
    
  2. Manual setup:

    executor = CodeExecutor(backend="docker")
    executor.setup_container()
    
  3. 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:

  • matplotlib
  • pandas
  • numpy
  • jupyter
  • nbconvert
  • ipynb-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 examples
  • ai_analyst/ - Complete Streamlit dashboard application
  • README.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_dir setting

๐Ÿ“ฆ 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

๐Ÿ”— Links

โญ 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

codibox-1.0.2.tar.gz (19.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

codibox-1.0.2-py3-none-any.whl (17.7 kB view details)

Uploaded Python 3

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

Hashes for codibox-1.0.2.tar.gz
Algorithm Hash digest
SHA256 e5b4e0583cd2a82d8b1fb97387535da1a08a954928b587deff5b52b09a0b1e7b
MD5 495a75e06f8c221de0c8b0158a8f1034
BLAKE2b-256 6a1910315478595b3b6762297c5c7239864a5963ff475a5569ef38709bb41324

See more details on using hashes here.

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

Hashes for codibox-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 a6e1dc3a98985bba258f32080996b78715b6b2c7134981c5a0738a0f01147f95
MD5 aed7ca298fac2ebdc4325147e2056b6a
BLAKE2b-256 dad1a631f4b503909d3a84a0b0fcc9720b5541401b9696fbd09b5847489670d3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page