Skip to main content
Most real workloads need data. This tutorial shows you how to get files into a sandbox, process them, and get results back out. You’ll learn three methods and when to use each one.

Method comparison

MethodDirectionBest forSize limit
copy_in() / copy_out()Host ↔ GuestFiles and directoriesLarge files
Volume mountsBoth (shared)Datasets, config filesNo limit
exec + base64EitherSmall inline data~1 MB (shell limit)

Prerequisites

pip install boxlite

Method 1: copy_in / copy_out

The most common approach. Upload a file, process it, download the results.
file_transfer.py
import asyncio
import boxlite


async def main():
    async with boxlite.SimpleBox(image="python:slim") as box:
        # Upload a script into the box
        # Note: destination must be a directory path, not a file path
        await box.exec("mkdir", "-p", "/workspace")
        await box.copy_in("/host/script.py", "/workspace/")

        # Run the script
        result = await box.exec("python", "/workspace/script.py")
        print(f"Exit code: {result.exit_code}")
        print(result.stdout)

        # Download the results
        await box.copy_out("/workspace/output.json", "/host/")


if __name__ == "__main__":
    asyncio.run(main())
When to use: Dynamic per-request files — scripts, input data, configuration that varies across runs.

Method 2: Volume mounts

Mount a host directory directly into the box. Files are shared in real time — no explicit copy step needed.
volume_mount.py
import asyncio
import boxlite


async def main():
    async with boxlite.SimpleBox(
        image="python:slim",
        volumes=[
            ("/host/datasets", "/mnt/data", True),      # Read-only input
            ("/host/results", "/mnt/results", False),    # Writable output
        ],
    ) as box:
        # Input data is already available at /mnt/data
        result = await box.exec(
            "python", "-c",
            "import os; print(os.listdir('/mnt/data'))"
        )
        print(result.stdout)

        # Write results — they appear on the host immediately
        await box.exec(
            "python", "-c",
            "open('/mnt/results/output.txt', 'w').write('done')"
        )


if __name__ == "__main__":
    asyncio.run(main())
When to use: Shared datasets or configuration that multiple boxes need access to. Use read-only mode for input data to prevent accidental modification.
Volume mounts give the guest direct access to host files. Always use read-only mode (True) for input data. Only use False for designated output directories.

Method 3: Inline data via base64

For small payloads (under ~1 MB), you can send data through a shell command without touching the filesystem.
inline_base64.py
import asyncio
import base64
import boxlite


async def main():
    async with boxlite.SimpleBox(image="python:slim") as box:
        # Encode a small script as base64
        data = b"print('hello from transferred script')"
        encoded = base64.b64encode(data).decode()

        # Send and execute in one command
        result = await box.exec(
            "sh", "-c",
            f"echo {encoded} | base64 -d > /tmp/script.py && python /tmp/script.py",
        )
        print(result.stdout)


if __name__ == "__main__":
    asyncio.run(main())
When to use: Trivially small payloads where you want to avoid the overhead of copy_in. Not suitable for binary files or anything over ~1 MB.

Putting it together

Here’s a realistic workflow: upload a CSV, run analysis code on it, and download the results.
full_workflow.py
import asyncio
import boxlite


async def main():
    async with boxlite.SimpleBox(
        image="python:slim",
        memory_mib=1024,
    ) as box:
        # 1. Create workspace directory
        await box.exec("mkdir", "-p", "/workspace")

        # 2. Upload the input data
        await box.copy_in("/host/sales_data.csv", "/workspace/")

        # 3. Upload the analysis script
        await box.copy_in("/host/analyze.py", "/workspace/")

        # 4. Run the analysis
        result = await box.exec("python", "/workspace/analyze.py")
        print(f"Analysis completed (exit code: {result.exit_code})")
        print(result.stdout)

        # 5. Download the results
        await box.copy_out("/workspace/report.json", "/host/")
        print("Results saved to /host/report.json")


if __name__ == "__main__":
    asyncio.run(main())
Use copy_in/copy_out for dynamic per-request files. Use volume mounts for shared datasets. Use inline base64 only for trivially small payloads.

What’s next?

Connect to an LLM

Let an LLM generate code and run it in your sandbox automatically.

AI agent integration

Production patterns: security presets, concurrency, timeout handling, and resource limits.