OpenEdx Codejail容器导入Matplotlib报错:无可用临时目录
OpenEdx Codejail导入Matplotlib报错解决方案
问题背景
- 部署环境:Tutor搭建的OpenEdx平台(版本:openedx-mfe:14.0.1),安装eduNEXT的Codejail插件(版本:codejailservice:14.1.0)
- 异常现象:在Codejail容器内直接执行
import matplotlib正常,但在OpenEdx高级模块(Advanced Block)的Problem代码块中执行相同导入时报错;import os可正常运行。
报错信息
cannot create LoncapaProblem block-v1:VUP+Math101+2022+type@problem+block@3319c4e42da64a74b0e40f048e3f2599: Error while executing script code: Couldn't execute jailed code: stdout: b'', stderr: b'Traceback (most recent call last): File "jailed_code", line 19, in <module> exec(code, g_dict) File "<string>", line 66, in <module> File "/sandbox/venv/lib/python3.8/site-packages/matplotlib/__init__.py", line 921, in <module> dict.update(rcParams, rc_params_in_file(matplotlib_fname())) File "/sandbox/venv/lib/python3.8/site-packages/matplotlib/__init__.py", line 602, in matplotlib_fname for fname in gen_candidates(): File "/sandbox/venv/lib/python3.8/site-packages/matplotlib/__init__.py", line 599, in gen_candidates yield os.path.join(get_configdir(), 'matplotlibrc') File "/sandbox/venv/lib/python3.8/site-packages/matplotlib/__init__.py", line 239, in wrapper ret = func(**kwargs) File "/sandbox/venv/lib/python3.8/site-packages/matplotlib/__init__.py", line 502, in get_configdir return get_config_or_cache_dir(_get_xdg_config_dir()) File "/sandbox/venv/lib/python3.8/site-packages/matplotlib/__init__.py", line 474, in get_config_or_cache_dir tempfile.mkdtemp(prefix="matplotlib-") File "/opt/pyenv/versions/3.8.6_sandbox/lib/python3.8/tempfile.py", line 347, in mkdtemp prefix, suffix, dir, output_type = sanitize_params(prefix, suffix, dir) File "/opt/pyenv/versions/3.8.6_sandbox/lib/python3.8/tempfile.py", line 117, in sanitize_params dir = gettempdir() File "/opt/pyenv/versions/3.8.6_sandbox/lib/python3.8/tempfile.py", line 286, in gettempdir tempdir = get_default_tempdir() File "/opt/pyenv/versions/3.8.6_sandbox/lib/python3.8/tempfile.py", line 218, in _get_default_tempdir raise FileNotFoundError(_errno.ENOENT, FileNotFoundError: [Errno 2] No usable temporary directory found in ['/tmp', '/var/tmp', '/usr/tmp', '/tmp/codejail-lbfd69da'] ' with status code: 1. For more information check Codejail Service logs.
Codejail服务日志
{"log":"[pid: 6|app: 0|req: 20/39] 172.18.0.10 () {36 vars in 483 bytes} [Tue Nov 22 11:24:59 2022] POST /api/v0/code-exec => generated 1978 bytes in 742 msecs (HTTP/1.1 200) 2 headers in 73 bytes (1 switches on core 0)\n","stream":"stderr","time":"2022-11-22T11:25:00.151315626Z"} {"log":"2022-11-22 11:26:23,304 INFO 9 [codejailservice.app] code_exec_service.py:52 - Running problem_id:53fbaa04859f41989ab967c15a12c013 jailed code for course_id:course-v1:VUP+Math101+2022 ...\n","stream":"stderr","time":"2022-11-22T11:26:23.30489438Z"} {"log":"2022-11-22 11:26:23,343 INFO 9 [codejailservice.app] code_exec_service.py:73 - Jailed code was executed in 0.03849988000001758 seconds.\n","stream":"stderr","time":"2022-11-22T11:26:23.343618965Z"} {"log":"[pid: 9|app: 0|req: 20/40] 172.18.0.10 () {36 vars in 483 bytes} [Tue Nov 22 11:26:23 2022] POST /api/v0/code-exec => generated 73 bytes in 40 msecs (HTTP/1.1 200) 2 headers in 71 bytes (1 switches on core 0)\n","stream":"stderr","time":"2022-11-22T11:26:23.344178308Z"} {"log":"2022-11-23 04:15:24,786 INFO 6 [codejailservice.app] code_exec_service.py:52 - Running problem_id:3319c4e42da64a74b0e40f048e3f2599 jailed code for course_id:course-v1:VUP+Math101+2022 ...\n","stream":"stderr","time":"2022-11-23T04:15:24.786287416Z"} {"log":"2022-11-23 04:15:25,582 ERROR 6 [codejailservice.app] code_exec_service.py:70 - Error found while executing jailed code.\n","stream":"stderr","time":"2022-11-23T04:15:25.582527974Z"} {"log":"[pid: 6|app: 0|req: 21/41] 172.18.0.10 () {36 vars in 483 bytes} [Wed Nov 23 04:15:24 2022] POST /api/v0/code-exec => generated 1978 bytes in 798 msecs (HTTP/1.1 200) 2 headers in 73 bytes (1 switches on core 0)\n","stream":"stderr","time":"2022-11-23T04:15:25.583132326Z"} {"log":"2022-11-23 06:00:15,150 INFO 9 [codejailservice.app] code_exec_service.py:52 - Running problem_id:3319c4e42da64a74b0e40f048e3f2599 jailed code for course_id:course-v1:VUP+Math101+2022 ...\n","stream":"stderr","time":"2022-11-23T06:00:15.15073834Z"} {"log":"2022-11-23 06:00:15,891 ERROR 9 [codejailservice.app] code_exec_service.py:70 - Error found while executing jailed code.\n","stream":"stderr","time":"2022-11-23T06:00:15.8916806Z"} {"log":"[pid: 9|app: 0|req: 21/42] 172.18.0.10 () {36 vars in 483 bytes} [Wed Nov 23 06:00:15 2022] POST /api/v0/code-exec => generated 1978 bytes in 742 msecs (HTTP/1.1 200) 2 headers in 73 bytes (1 switches on core 0)\n","stream":"stderr","time":"2022-11-23T06:00:15.892225441Z"}
原因分析
Matplotlib初始化时会尝试创建临时配置目录,但Codejail的沙箱环境对临时目录的读写权限做了限制,导致无法创建或访问指定的临时目录,从而抛出FileNotFoundError。
解决方案
1. 代码层面预配置Matplotlib
在Problem代码块中,先配置环境变量和Matplotlib参数,避免初始化时尝试创建临时目录:
<problem> <script type="loncapa/python"> import os # 指定Matplotlib配置目录为沙箱内可访问路径 os.environ['MPLCONFIGDIR'] = '/tmp/codejail-matplotlib' # 确保目录存在 os.makedirs(os.environ['MPLCONFIGDIR'], exist_ok=True) # 设置非交互式后端(避免图形界面依赖) import matplotlib matplotlib.use('Agg') # 后续可正常使用Matplotlib import matplotlib.pyplot as plt </script> </problem>
2. 调整Codejail沙箱权限配置
- 进入Codejail容器:
tutor exec codejail bash
- 编辑Codejail配置文件(通常路径为
/etc/codejail/config.py),添加允许访问的临时目录:
SAFE_TMP_DIRS = ['/tmp', '/tmp/codejail-*', '/tmp/codejail-matplotlib']
- 重启Codejail服务:
tutor restart codejail
3. 预生成Matplotlib配置文件
在Codejail沙箱环境中提前生成Matplotlib配置文件,避免运行时创建:
- 进入沙箱Python环境:
tutor exec codejail /opt/pyenv/versions/3.8.6_sandbox/bin/python
- 执行以下代码生成配置:
import matplotlib matplotlib.use('Agg') matplotlib.matplotlib_fname()
验证
在OpenEdx的Problem代码块中运行修改后的代码,检查是否能正常导入Matplotlib并执行绘图逻辑,无权限类报错即为修复成功。
内容的提问来源于stack exchange,提问作者Ishfaq Babar
相关产品推荐
相关产品推荐

