dify-sandbox 使用python 虚拟环境本地开发
为啥使用虚拟环境
本地直接使用 pip install 提示错误信息,要在系统范围内安装包,建议使用 apt install python3-xyz 。系统范围的依赖不建议修改,各开发环境之间依赖还是隔离开比较好,各个环境可能需要不同版本的依赖包
bash
$ pip install httpx
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.
If you wish to install a non-Debian-packaged Python package,
create a virtual environment using python3 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
sure you have python3-full installed.
If you wish to install a non-Debian packaged Python application,
it may be easiest to use pipx install xyz, which will manage a
virtual environment for you. Make sure you have pipx installed.
See /usr/share/doc/python3.12/README.venv for more information.
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.
环境准备
- 创建虚拟环境
bash
$ python3 -m venv .dify-sandbox-python3
- 激活虚拟环境
bash
$ source .dify-sandbox-python3/bin/activate
- 检查 python 命令
bash
$ python
Python 3.12.3 (main, Mar 3 2026, 12:15:18) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
- 查看相关pip 配置
bash
$ pip config list
global.index-url='https://mirrors.ustc.edu.cn/pypi/simple'
- 获取 python 默认加载模块路径
bash
$ python
Python 3.12.3 (main, Mar 3 2026, 12:15:18) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print(sys.path)
['', '/usr/lib/python312.zip', '/usr/lib/python3.12', '/usr/lib/python3.12/lib-dynload', '/home/scd/code/go/dify/.dify-sandbox-python3/lib/python3.12/site-packages']
>>>
- 修改 dify-sandbox 的 conf/config.yaml
将第5步获取的模块路径复制到 python_lib_path
yaml
app:
port: 8194
debug: True
key: dify-sandbox
max_workers: 4
max_requests: 50
worker_timeout: 5
python_path: python
nodejs_path: /usr/local/node-v24.14.1/bin/node
python_lib_path:
- "/usr/lib/python3.12"
- "/home/scd/code/go/dify/.dify-sandbox-python3/lib/python3.12/site-packages"
- "/usr/lib/x86_64-linux-gnu"
- "/etc/ssl/certs/ca-certificates.crt"
- "/etc/nsswitch.conf"
- "/etc/hosts"
- "/etc/resolv.conf"
- "/etc/localtime"
- "/usr/share/zoneinfo"
- "/etc/timezone"
enable_network: True # please make sure there is no network risk in your environment
enable_preload: False # please keep it as False for security purposes
log_path: "./logs" # path to store log files, default is "./logs"
allowed_syscalls: # please leave it empty if you have no idea how seccomp works
proxy:
socks5: ''
http: ''
https: ''
启动服务,验证相关接口
- 清除sandbox-python相关的 lib 包,避免影响验证环境是否可行
bash
# rm -rf /var/sandbox/sandbox-python/*
- 激活虚拟环境,启动服务
bash
# source ../.dify-sandbox-python3/bin/activate
# ./main
{"time":"2026-04-16T22:19:35.068617743+08:00","level":"INFO","msg":"initializing nodejs runner environment"}
{"time":"2026-04-16T22:19:35.124300637+08:00","level":"INFO","msg":"nodejs runner environment initialized"}
{"time":"2026-04-16T22:19:35.125273122+08:00","level":"INFO","msg":"initializing python runner environment"}
{"time":"2026-04-16T22:19:35.126686582+08:00","level":"INFO","msg":"python runner environment initialized"}
{"time":"2026-04-16T22:19:35.127147413+08:00","level":"INFO","msg":"network has been enabled"}
{"time":"2026-04-16T22:19:35.127189865+08:00","level":"INFO","msg":"config init success"}
{"time":"2026-04-16T22:19:35.127256556+08:00","level":"INFO","msg":"runner dependencies init success"}
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /health --> github.com/langgenius/dify-sandbox/internal/controller.Setup.func1 (5 handlers)
{"time":"2026-04-16T22:19:35.127331159+08:00","level":"INFO","msg":"setting max requests","max":50}
{"time":"2026-04-16T22:19:35.127349763+08:00","level":"INFO","msg":"setting max workers","max":4}
[GIN-debug] POST /v1/sandbox/run --> github.com/langgenius/dify-sandbox/internal/controller.RunSandboxController (9 handlers)
[GIN-debug] GET /v1/sandbox/dependencies --> github.com/langgenius/dify-sandbox/internal/controller.GetDependencies (6 handlers)
[GIN-debug] POST /v1/sandbox/dependencies/update --> github.com/langgenius/dify-sandbox/internal/controller.UpdateDependencies (6 handlers)
[GIN-debug] GET /v1/sandbox/dependencies/refresh --> github.com/langgenius/dify-sandbox/internal/controller.RefreshDependencies (6 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :8194
{"time":"2026-04-16T22:19:35.127444004+08:00","level":"INFO","msg":"installing python dependencies"}
{"time":"2026-04-16T22:19:35.127526811+08:00","level":"INFO","msg":"python dependencies installed"}
{"time":"2026-04-16T22:19:35.127539828+08:00","level":"INFO","msg":"initializing python dependencies sandbox"}
- 运行测试接口
test_dify_sandbox.sh 脚本内容
bash
$ cat test_dify_sandbox.sh
#!/bin/bash
REQUEST_HOST=http://localhost:8194
X_API_KEY=dify-sandbox
# 健康检查接口
echo "健康检查接口:/health"
curl ${REQUEST_HOST}/health
# Python3 示例
echo ""
echo "Python3 运行代码:/v1/sandbox/run"
curl -X POST ${REQUEST_HOST}/v1/sandbox/run \
-H "Content-Type: application/json" \
-H "X-Api-Key: ${X_API_KEY}" \
-d '{
"language": "python3",
"code": "import json\nperson = {\"name\": \"John\", \"age\": 30, \"city\": \"New York\"}\njson_str = json.dumps(person)\nprint(json_str)",
"preload": "",
"enable_network": false
}'
echo ""
echo "Node.js 运行代码:/v1/sandbox/run"
# Node.js 示例
curl -X POST ${REQUEST_HOST}/v1/sandbox/run \
-H "Content-Type: application/json" \
-H "X-Api-Key: ${X_API_KEY}" \
-d '{
"language": "nodejs",
"code": "const person = {name: \"John\", age: 30, city: \"New York\"};\nconst jsonString = JSON.stringify(person);\nconsole.log(jsonString);",
"preload": "",
"enable_network": false
}'
echo ""
echo "更新依赖 复制python_lib_path依赖:/v1/sandbox/dependencies/update"
curl -X POST ${REQUEST_HOST}/v1/sandbox/dependencies/update \
-H "Content-Type: application/json" \
-H "X-Api-Key: ${X_API_KEY}" \
-d '{"language": "python3"}'
echo ""
echo "刷新依赖dependencies/python-requirements.txt依赖:/v1/sandbox/dependencies/refresh"
curl -X GET ${REQUEST_HOST}/v1/sandbox/dependencies/refresh \
-H "Content-Type: application/json" \
-H "X-Api-Key: ${X_API_KEY}" \
-d '{"language": "python3"}'
echo ""
echo "获取已安装依赖:/v1/sandbox/dependencies"
curl -X GET ${REQUEST_HOST}/v1/sandbox/dependencies \
-H "Content-Type: application/json" \
-H "X-Api-Key: ${X_API_KEY}" \
-d '{"language": "python3"}'
echo ""
执行结果
bash
$ sh test_dify_sandbox.sh
健康检查接口:/health
"ok"
Python3 运行代码:/v1/sandbox/run
{"code":0,"message":"success","data":{"error":"","stdout":"{\"name\": \"John\", \"age\": 30, \"city\": \"New York\"}\n"}}
Node.js 运行代码:/v1/sandbox/run
{"code":0,"message":"success","data":{"error":"","stdout":"{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}\n"}}
更新依赖 复制python_lib_path依赖:/v1/sandbox/dependencies/update
{"code":0,"message":"success","data":{}}
刷新依赖dependencies/python-requirements.txt依赖:/v1/sandbox/dependencies/refresh
{"code":0,"message":"success","data":{"dependencies":[{"name":"jinja2","version":""},{"name":"httpx","version":""},{"name":"requests","version":""}]}}
获取已安装依赖:/v1/sandbox/dependencies
{"code":0,"message":"success","data":{"dependencies":[{"name":"jinja2","version":""},{"name":"httpx","version":""},{"name":"requests","version":""}]}}