Django调用外部脚本时出现Internal Server Error与MultiValueDictKeyError报错
问题原因
你碰到的两个报错根源都是同一个问题:subprocess.run()返回的stdout是未处理的字节流类型:
- 字节流直接转字符串会自带前缀
b',同时你调用的image.py输出结尾自带换行符,所以传递给模板的edit_url实际值是b'/media/temp.png\n',模板渲染成链接后就产生了你日志里异常的GET /external/b'/media/temp.png/n'请求 - 这个异常请求是GET类型,不会携带上传的文件数据,访问
external视图时执行request.FILES['image']自然会抛出MultiValueDictKeyError报错
解决方案
修改views.py的external函数即可,共3处调整:
- 对
subprocess.run()返回的输出做解码、去首尾空白处理,消除b'前缀和换行符 - 修正传给
image.py的文件路径参数(你之前传的是文件对象不是路径,属于隐藏bug) - 给视图加请求方法限制,避免无效GET请求报错
修改后的完整external函数代码如下:
# 先导入需要的装饰器,放在文件头部 from django.views.decorators.http import require_http_methods @require_http_methods(["POST"]) def external(request): inp = request.POST.get('param', False) image = request.FILES['image'] print("image is ", image) fs = FileSystemStorage() filename = fs.save(image.name, image) # 取本地文件绝对路径,传给image.py用 file_local_path = fs.path(filename) templateurl = fs.url(filename) print("file raw url", filename) print("file full path", file_local_path) print("template url", templateurl) # 执行脚本时指定encoding=utf-8直接拿到字符串,不用手动解码 out = run( [sys.executable,'//home//felix//ucmr//button-python-click//Image_Edit_Html_Button_Run_Python_Script//test.py', inp], shell=False, stdout=PIPE, encoding='utf-8' ) image_res = run( [sys.executable,'//home//felix//ucmr//button-python-click//Image_Edit_Html_Button_Run_Python_Script//image.py', file_local_path, filename], shell=False, stdout=PIPE, encoding='utf-8' ) # 去掉输出首尾的换行、空格等空白字符 out_content = out.stdout.strip() edit_url = image_res.stdout.strip() print(out) print(edit_url) return render(request,'home.html',{'data': out_content,'raw_url': templateurl,'edit_url': edit_url})
内容的提问来源于stack exchange,提问作者Felix BoeVR
相关产品推荐
相关产品推荐

