树莓派中通过Python subprocess运行JS脚本并获取返回值方法问询
Hey there! Since you can't rewrite your Node.js sensor script (thanks to that exclusive Node.js library), let's go through practical ways to get those sensor readings into your Python code. Here are the most reliable approaches:
1. Pass Data via Standard Output (stdout) – Simplest Approach
This is the easiest method for one-off sensor reads. The idea is to have your Node.js script output sensor data as a JSON string (easy to parse in Python), then capture that output in your Python script.
Step 1: Modify Your test.js to Output JSON
Update your script to print the sensor data to stdout after converting it to JSON. This ensures Python can easily parse it:
const sensorLib = require('your-exclusive-sensor-library'); // Async function to read sensor data async function fetchSensorData() { try { // Replace with your actual sensor reading logic const sensorReading = await sensorLib.getSensorData(); // Output JSON to stdout (Python will capture this) console.log(JSON.stringify(sensorReading)); } catch (err) { // Send errors to stderr (Python can catch this too) console.error(`Sensor read error: ${err.message}`); process.exit(1); // Non-zero exit code signals failure to Python } } fetchSensorData();
Step 2: Capture and Parse Output in Python
Instead of subprocess.check_call, use subprocess.check_output to capture the stdout from the Node.js script, then parse the JSON:
import subprocess import json def get_sensor_reading(): try: # Run the npm script and capture stdout raw_output = subprocess.check_output( ['npm', 'run', 'test'], stderr=subprocess.STDOUT, # Include stderr in output for debugging text=True # Return string instead of bytes ) # Parse the JSON output sensor_data = json.loads(raw_output.strip()) return sensor_data except subprocess.CalledProcessError as e: print(f"Failed to run Node.js script: {e.output}") return None except json.JSONDecodeError: print("Failed to parse sensor data (invalid JSON)") return None # Example usage sensor_reading = get_sensor_reading() if sensor_reading: print(f"Got sensor data: {sensor_reading}")
2. Stream Real-Time Sensor Data
If you need continuous, real-time readings (e.g., polling the sensor every second), use subprocess.Popen to keep the Node.js process running and read its output line by line.
Modified test.js for Streaming
const sensorLib = require('your-exclusive-sensor-library'); async function streamSensorData() { try { while (true) { const sensorReading = await sensorLib.getSensorData(); console.log(JSON.stringify(sensorReading)); await new Promise(resolve => setTimeout(resolve, 1000)); // Wait 1 second between reads } } catch (err) { console.error(`Stream error: ${err.message}`); process.exit(1); } } streamSensorData();
Python Code to Stream Data
import subprocess import json def stream_sensor_data(): try: # Start the Node.js process with persistent stdout process = subprocess.Popen( ['npm', 'run', 'test'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1, # Line-buffered output universal_newlines=True ) # Read output line by line for line in process.stdout: cleaned_line = line.strip() if cleaned_line: try: sensor_data = json.loads(cleaned_line) yield sensor_data except json.JSONDecodeError: print(f"Invalid JSON line: {cleaned_line}") # Check if process exited unexpectedly process.wait() if process.returncode != 0: print(f"Stream process exited with code: {process.returncode}") except Exception as e: print(f"Failed to start stream: {e}") # Example usage: iterate over real-time readings for reading in stream_sensor_data(): print(f"Real-time sensor reading: {reading}")
3. Use a Local HTTP Server (For More Complex Workflows)
If you need bidirectional communication or want to integrate with other tools, spin up a lightweight HTTP server in Node.js and have Python send requests to fetch data.
Node.js HTTP Server (test.js)
const sensorLib = require('your-exclusive-sensor-library'); const http = require('http'); const PORT = 3000; const server = http.createServer(async (req, res) => { // Handle GET requests to /sensor-data if (req.method === 'GET' && req.url === '/sensor-data') { try { const sensorReading = await sensorLib.getSensorData(); res.writeHead(200, {'Content-Type': 'application/json'}); res.end(JSON.stringify(sensorReading)); } catch (err) { res.writeHead(500, {'Content-Type': 'application/json'}); res.end(JSON.stringify({error: 'Failed to read sensor'})); } return; } // Handle invalid routes res.writeHead(404); res.end('Not found'); }); server.listen(PORT, () => { console.log(`Sensor data server running on http://localhost:${PORT}`); });
Python Code to Fetch Data via HTTP
import requests def get_sensor_data_via_http(): try: response = requests.get('http://localhost:3000/sensor-data') response.raise_for_status() # Raise error for HTTP status codes >=400 return response.json() except requests.exceptions.RequestException as e: print(f"HTTP request failed: {e}") return None # Example usage sensor_data = get_sensor_data_via_http() if sensor_data: print(f"Sensor data from HTTP server: {sensor_data}")
Note: You'll need to start the Node.js server first (either manually or via Python using subprocess.Popen before making requests).
Which Approach Should You Choose?
- One-off reads: Go with the stdout/JSON method (it's lightweight and requires no extra dependencies).
- Real-time streaming: Use the
Popenline-reading method or the HTTP server. - Complex interactions: The HTTP server or other IPC methods (like Unix sockets) are better suited.
内容的提问来源于stack exchange,提问作者Samuel Vergeiner

