/ sdks / code-interpreter / python / README.md
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).