如何在Django中捕获Python脚本输出并展示或存入模型?
解决Django捕获外部脚本输出并展示的问题
首先你要明确:os.system()只会返回命令的退出码(0表示运行成功,非0代表错误),并不是脚本的实际输出内容——你现在传给模板的data其实就是这个退出码,不是终端里看到的脚本输出,这就是网页拿不到正确内容的核心原因。
方案一:直接在Django中捕获脚本输出(推荐临时展示场景)
用Python官方推荐的subprocess模块替代os.system,它能直接捕获脚本的标准输出和错误输出。修改你的view代码如下:
import subprocess def home_output(request): commandRun = 'python script.py' # 运行命令并捕获输出,text=True让返回结果为字符串而非字节 result = subprocess.run( commandRun, shell=True, capture_output=True, text=True ) # 提取脚本的标准输出、错误输出和退出码 stdout_content = result.stdout stderr_content = result.stderr return_code = result.returncode # 将输出数据传给模板 return render(request, 'home-view.html', { 'stdout': stdout_content, 'stderr': stderr_content, 'return_code': return_code })
然后在home-view.html中添加渲染逻辑,比如:
<h3>脚本运行输出</h3> {% if stdout %} <pre>{{ stdout }}</pre> {% endif %} {% if stderr %} <h4>错误信息</h4> <pre style="color: #dc3545;">{{ stderr }}</pre> {% endif %} <p>退出码:{{ return_code }}</p>
方案二:将输出存入Django Model(适合持久化需求场景)
如果脚本输出需要长期保存、后续查询,或者要和其他业务数据关联,就可以将输出存入数据库模型:
- 先在
models.py中定义存储模型:
from django.db import models class ScriptExecutionRecord(models.Model): stdout = models.TextField(blank=True, verbose_name="标准输出") stderr = models.TextField(blank=True, verbose_name="错误输出") return_code = models.IntegerField(default=0, verbose_name="退出码") created_at = models.DateTimeField(auto_now_add=True, verbose_name="运行时间") def __str__(self): return f"脚本运行记录:{self.created_at}"
执行python manage.py makemigrations和python manage.py migrate命令,创建对应的数据库表。
- 修改view代码,捕获输出后保存到模型:
import subprocess from .models import ScriptExecutionRecord def home_output(request): commandRun = 'python script.py' result = subprocess.run( commandRun, shell=True, capture_output=True, text=True ) # 将输出保存到数据库 record = ScriptExecutionRecord.objects.create( stdout=result.stdout, stderr=result.stderr, return_code=result.returncode ) # 将记录对象传给模板 return render(request, 'home-view.html', {'record': record})
- 模板中渲染存储的记录:
<h3>脚本运行记录(已保存)</h3> <pre>{{ record.stdout }}</pre> {% if record.stderr %} <h4>错误信息</h4> <pre style="color: #dc3545;">{{ record.stderr }}</pre> {% endif %} <p>运行时间:{{ record.created_at }}</p> <p>退出码:{{ record.return_code }}</p>
注意事项
- 如果脚本不在Django项目的当前工作目录,要写绝对路径(比如
/usr/local/scripts/script.py),避免出现找不到脚本的错误。 - 若命令中包含用户输入的内容,禁止使用
shell=True,要将命令拆分为列表形式(比如['python', 'script.py', user_input]),防止命令注入攻击。
内容的提问来源于stack exchange,提问作者user15109593
相关产品推荐
相关产品推荐

