README.md
1 # OpenSandbox Code Interpreter SDK for Python 2 3 English | [中文](README_zh.md) 4 5 A Python SDK for executing code in secure, isolated sandboxes. It provides a high-level API for running Python, Java, 6 Go, TypeScript, and other languages safely, with support for code execution contexts. 7 8 ## Prerequisites 9 10 This SDK requires a Docker image containing the Code Interpreter runtime environment. You must use the 11 `opensandbox/code-interpreter` image (or a derivative) which includes pre-installed runtimes for Python, Java, Go, 12 Node.js, etc. 13 14 For detailed information about supported languages and versions, refer to the 15 [Environment Documentation](../../../sandboxes/code-interpreter/README.md). 16 17 ## Installation 18 19 ### pip 20 21 ```bash 22 pip install opensandbox-code-interpreter 23 ``` 24 25 ### uv 26 27 ```bash 28 uv add opensandbox-code-interpreter 29 ``` 30 31 ## Quick Start 32 33 The following example demonstrates how to create a sandbox with a specific runtime configuration and execute a simple 34 script. 35 36 ```python 37 import asyncio 38 from datetime import timedelta 39 40 from code_interpreter import CodeInterpreter, SupportedLanguage 41 from opensandbox import Sandbox 42 from opensandbox.config import ConnectionConfig 43 44 45 async def main() -> None: 46 # 1. Configure connection 47 config = ConnectionConfig( 48 domain="api.opensandbox.io", 49 api_key="your-api-key", 50 request_timeout=timedelta(seconds=60), 51 ) 52 53 # 2. Create a Sandbox with the code-interpreter image + runtime versions 54 sandbox = await Sandbox.create( 55 "opensandbox/code-interpreter:v1.0.2", 56 connection_config=config, 57 entrypoint=["/opt/opensandbox/code-interpreter.sh"], 58 env={ 59 "PYTHON_VERSION": "3.11", 60 "JAVA_VERSION": "17", 61 "NODE_VERSION": "20", 62 "GO_VERSION": "1.24", 63 }, 64 ) 65 66 # 3. Use async context manager to ensure local resources are cleaned up 67 async with sandbox: 68 # 4. Create CodeInterpreter wrapper 69 interpreter = await CodeInterpreter.create(sandbox=sandbox) 70 71 # 5. Create an execution context (Python) 72 context = await interpreter.codes.create_context(SupportedLanguage.PYTHON) 73 74 # 6. Run code 75 result = await interpreter.codes.run( 76 "import sys\nprint(sys.version)\nresult = 2 + 2\nresult", 77 context=context, 78 ) 79 80 # Alternatively, you can pass a language directly (recommended: SupportedLanguage.*). 81 # This uses the default context for that language (state can persist across runs). 82 # result = await interpreter.codes.run("print('hi')", language=SupportedLanguage.PYTHON) 83 84 # 7. Print output 85 if result.result: 86 print(result.result[0].text) 87 88 # 8. Cleanup remote instance (optional but recommended) 89 await sandbox.kill() 90 91 92 if __name__ == "__main__": 93 asyncio.run(main()) 94 ``` 95 96 ### Synchronous Quick Start 97 98 If you prefer a synchronous API, use `SandboxSync` + `CodeInterpreterSync`: 99 100 ```python 101 from datetime import timedelta 102 103 import httpx 104 from code_interpreter import CodeInterpreterSync 105 from opensandbox import SandboxSync 106 from opensandbox.config import ConnectionConfigSync 107 108 config = ConnectionConfigSync( 109 domain="api.opensandbox.io", 110 api_key="your-api-key", 111 request_timeout=timedelta(seconds=60), 112 transport=httpx.HTTPTransport(limits=httpx.Limits(max_connections=20)), 113 ) 114 115 sandbox = SandboxSync.create( 116 "opensandbox/code-interpreter:v1.0.2", 117 connection_config=config, 118 entrypoint=["/opt/opensandbox/code-interpreter.sh"], 119 env={"PYTHON_VERSION": "3.11"}, 120 ) 121 with sandbox: 122 interpreter = CodeInterpreterSync.create(sandbox=sandbox) 123 result = interpreter.codes.run("result = 2 + 2\nresult") 124 if result.result: 125 print(result.result[0].text) 126 sandbox.kill() 127 ``` 128 129 ### Installing Python packages at runtime 130 131 You can install packages directly via `sandbox.commands.run(...)`: 132 133 ```python 134 execution = await sandbox.commands.run("pip install pandas numpy") 135 ``` 136 137 ## Runtime Configuration 138 139 ### Docker Image 140 141 The Code Interpreter SDK relies on a specialized environment. Ensure your sandbox provider has the 142 `opensandbox/code-interpreter` image available. 143 144 ### Language Version Selection 145 146 You can specify the desired version of a programming language by setting the corresponding environment variable when 147 creating the `Sandbox`. 148 149 | Language | Environment Variable | Example Value | Default (if unset) | 150 | -------- | -------------------- | ------------- | ------------------ | 151 | Python | `PYTHON_VERSION` | `3.11` | Image default | 152 | Java | `JAVA_VERSION` | `17` | Image default | 153 | Node.js | `NODE_VERSION` | `20` | Image default | 154 | Go | `GO_VERSION` | `1.24` | Image default | 155 156 ## Usage Examples 157 158 ### 0. Run with `language` (default language context) 159 160 You can pass `language` directly (recommended: `SupportedLanguage.*`) and skip `create_context`. 161 When `context.id` is omitted, **execd will create/reuse a default session for that language**, so 162 state can persist across runs: 163 164 ```python 165 from code_interpreter import SupportedLanguage 166 167 execution = await interpreter.codes.run( 168 "result = 2 + 2\nresult", 169 language=SupportedLanguage.PYTHON, 170 ) 171 assert execution.result and execution.result[0].text == "4" 172 ``` 173 174 State persistence example (default Python context): 175 176 ```python 177 from code_interpreter import SupportedLanguage 178 179 await interpreter.codes.run("x = 42", language=SupportedLanguage.PYTHON) 180 execution = await interpreter.codes.run("result = x\nresult", language=SupportedLanguage.PYTHON) 181 assert execution.result and execution.result[0].text == "42" 182 ``` 183 184 ### 1. Java Code Execution 185 186 ```python 187 from code_interpreter import SupportedLanguage 188 189 ctx = await interpreter.codes.create_context(SupportedLanguage.JAVA) 190 execution = await interpreter.codes.run( 191 ( 192 'System.out.println("Calculating sum...");\n' 193 + "int a = 10;\n" 194 + "int b = 20;\n" 195 + "int sum = a + b;\n" 196 + 'System.out.println("Sum: " + sum);\n' 197 + "sum" 198 ), 199 context=ctx, 200 ) 201 202 print(execution.id) 203 for msg in execution.logs.stdout: 204 print(msg.text) 205 ``` 206 207 ### 2. Python with State Persistence 208 209 Variables defined in one execution are available in subsequent executions within the same context. 210 211 ```python 212 from code_interpreter import SupportedLanguage 213 214 ctx = await interpreter.codes.create_context(SupportedLanguage.PYTHON) 215 216 await interpreter.codes.run( 217 "users = ['Alice', 'Bob', 'Charlie']\nprint(len(users))", 218 context=ctx, 219 ) 220 221 result = await interpreter.codes.run( 222 "users.append('Dave')\nprint(users)\nresult = users\nresult", 223 context=ctx, 224 ) 225 ``` 226 227 ### 3. Streaming Output Handling 228 229 Handle stdout/stderr and execution events in real-time. 230 231 ```python 232 from opensandbox.models.execd import ExecutionHandlers 233 from code_interpreter import SupportedLanguage 234 235 async def on_stdout(msg): 236 print("STDOUT:", msg.text) 237 238 async def on_stderr(msg): 239 print("STDERR:", msg.text) 240 241 handlers = ExecutionHandlers(on_stdout=on_stdout, on_stderr=on_stderr) 242 243 ctx = await interpreter.codes.create_context(SupportedLanguage.PYTHON) 244 await interpreter.codes.run( 245 "import time\nfor i in range(5):\n print(i)\n time.sleep(0.5)", 246 context=ctx, 247 handlers=handlers, 248 ) 249 ``` 250 251 ### 4. Multi-Language Context Isolation 252 253 Different languages run in isolated environments. 254 255 ```python 256 from code_interpreter import SupportedLanguage 257 258 py_ctx = await interpreter.codes.create_context(SupportedLanguage.PYTHON) 259 go_ctx = await interpreter.codes.create_context(SupportedLanguage.GO) 260 261 await interpreter.codes.run("print('Running in Python')", context=py_ctx) 262 await interpreter.codes.run( 263 "package main\nfunc main() { println(\"Running in Go\") }", 264 context=go_ctx, 265 ) 266 ``` 267 268 ## Notes 269 270 - **Lifecycle**: `CodeInterpreter` wraps an existing `Sandbox` instance and reuses its connection configuration. 271 - **Asyncio/event loop**: avoid sharing long-lived clients across multiple event loops (e.g. pytest-asyncio defaults).