如何将subprocess调用test.py的字典列表输出转为JS可处理的JSON对象
Let's break down why you're ending up with a string instead of a parseable JSON object in your frontend, and fix it step by step:
1. The Root Problem: Invalid JSON Output from test.py
Your test.py is outputting a Python-style list of dictionaries, not valid JSON. Notice in your sample data:
data = [{'a': 12, 'name':'abc'}, {'a': 16, 'name':xyz}, {'a': 17, 'name': lmn}]
xyzandlmnare unquoted (they'd be treated as undefined variables in Python, which throws errors)- Python uses single quotes, but JSON requires double quotes for strings
Even if you printed this data directly, it won't be valid JSON—so when your frontend runs JSON.parse(), it can't convert the string into a proper object/array.
2. Fix test.py to Output Valid JSON
First, update test.py to serialize its output with the json module, which ensures standard JSON format:
import json # Generate your data as before (fix unquoted string values first!) data = [ {'a': 12, 'name':'abc'}, {'a': 16, 'name':'xyz'}, # Add quotes around string values {'a': 17, 'name': 'lmn'} # Add quotes here too ] # Output valid JSON to stdout print(json.dumps(data))
3. Update Backend Code to Handle the Output Correctly
Your current func1 and func2 have a few issues: missing function parameters, improper path formatting, and not properly handling the subprocess output as JSON. Here's the revised code:
Fix func1 (subprocess execution)
import subprocess import json from django.http import HttpResponse import settings def func1(arg1, arg2): # Add missing parentheses and parameters # Use f-strings for cleaner path/command formatting cmd = f'python {settings.BASE_DIR}/test.py {arg1} {arg2}' # Use text=True to get string output instead of bytes (Python 3.7+) p = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, text=True ) out, err = p.communicate() return (p.returncode, err, out)
Fix func2 (Django view)
def func2(request): # Fix typo: was "funct2" if request.GET: # Get arguments from the request (adjust based on your actual params) arg1 = request.GET.get('arg1') arg2 = request.GET.get('arg2') statuscode, err, resp = func1(arg1, arg2) if not err and statuscode == 0: try: # Parse the subprocess output into a Python object first parsed_data = json.loads(resp) # Return the parsed data as part of your JSON response return HttpResponse( json.dumps({ 'resp': parsed_data, 'status_code': statuscode, 'err': err }), content_type="application/json" ) except json.JSONDecodeError as e: # Handle invalid JSON from test.py gracefully return HttpResponse( json.dumps({ 'resp': None, 'status_code': 500, 'err': f'Invalid output from test.py: {str(e)}' }), content_type="application/json" ) else: # Handle errors from the subprocess execution return HttpResponse( json.dumps({ 'resp': None, 'status_code': statuscode, 'err': err }), content_type="application/json" )
4. Why This Works
- Valid JSON from test.py:
json.dumps()converts your Python list into a properly formatted JSON string with double quotes and valid syntax. - Proper output handling: Using
text=Trueinsubprocess.Popengives you a string directly, so you don't have to decode bytes manually. - Parsing before returning: By parsing
respinto a Python object withjson.loads(), when you serialize it again withjson.dumps()in the response, it becomes a valid JSON array that your frontend can parse withJSON.parse()to get a usable JavaScript array of objects.
Now when your frontend runs:
fetch('/your-view-url') .then(res => res.json()) .then(data => { const usableArray = data.resp; // usableArray is now a JS array of objects, not a string! });
内容的提问来源于stack exchange,提问作者Rachel

