如何在JavaScript代码中调用Python 3函数?支持传参及返回数据
Absolutely, there are several reliable ways to connect your Python lexer/parser with JavaScript so you can call those functions directly from JS, pass parameters, and get back results. Let’s walk through the most practical options with concrete steps:
1. Run Python in the Browser with WebAssembly (Pyodide)
If you need this to work directly in a browser (no backend required), Pyodide is your best bet—it compiles CPython to WebAssembly, letting you run full Python code right in the browser.
How to implement it:
- Include the Pyodide script in your HTML or load it via JS.
- Initialize the Pyodide environment and load your lexer/parser module.
- Call your Python functions from JS and convert the results to JS-compatible types.
Example code:
async function loadPyodideAndRun() { // Load Pyodide const pyodide = await loadPyodide(); // Option 1: Inject your Python code directly pyodide.runPython(` # Paste your lexer/parser code here, or import from a module def my_lexer(input_text): # Your lexer logic here return [("TOKEN_TYPE", token) for token in input_text.split()] def my_parser(tokens): # Your parser logic here return {"parsed": tokens, "status": "success"} `); // Option 2: Load a local Python file (requires serving files via HTTP) // await pyodide.loadPackage("micropip"); // const micropip = pyodide.pyimport("micropip"); // await micropip.install("./custom_lang.py"); // pyodide.runPython("from custom_lang import my_lexer, my_parser"); // Call Python functions from JS const inputText = "let x = 10"; const lexResult = pyodide.globals.get("my_lexer")(inputText); // Convert Python object to JS const jsLexResult = pyodide.toJs(lexResult); console.log("Lexer result:", jsLexResult); const parseResult = pyodide.globals.get("my_parser")(lexResult); const jsParseResult = pyodide.toJs(parseResult); console.log("Parser result:", jsParseResult); } // Initialize and run loadPyodideAndRun();
Pros & Cons:
- ✅ No backend needed, works entirely in the browser
- ✅ Full access to Python’s standard library and your custom code
- ❌ Initial load time can be slow (Pyodide is ~5MB)
- ❌ Slightly slower than native Python execution
2. Build a Python API Backend
If performance is a priority, or you already have a backend, wrap your lexer/parser in a simple API. You can use frameworks like FastAPI or Flask to expose endpoints that JS can call via HTTP requests.
How to implement it:
- Create a Python API with endpoints for your lexer and parser.
- Handle input/output with JSON (easy to serialize/deserialize between Python and JS).
- Call the API from JS using
fetchor a library like Axios.
Example FastAPI backend:
# main.py from fastapi import FastAPI, HTTPException from pydantic import BaseModel from custom_lang import my_lexer, my_parser # Import your actual functions app = FastAPI() # Define input schema class TextInput(BaseModel): text: str # Lexer endpoint @app.post("/api/lex") def lex(input_data: TextInput): try: result = my_lexer(input_data.text) return {"result": result} except Exception as e: raise HTTPException(status_code=400, detail=str(e)) # Parser endpoint @app.post("/api/parse") def parse(input_data: TextInput): try: result = my_parser(input_data.text) return {"result": result} except Exception as e: raise HTTPException(status_code=400, detail=str(e))
Example JS frontend call:
async function callLexer(inputText) { try { const response = await fetch("http://localhost:8000/api/lex", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ text: inputText }), }); if (!response.ok) throw new Error("API request failed"); const data = await response.json(); return data.result; } catch (err) { console.error("Lexer error:", err); return null; } } // Usage callLexer("let x = 10").then(result => console.log(result));
Pros & Cons:
- ✅ Native Python performance (no Wasm overhead)
- ✅ Easy to scale and maintain
- ❌ Requires running a backend server
- ❌ Needs to handle CORS if frontend is on a different domain (use FastAPI’s
CORSMiddlewareto fix this)
3. Call Python Scripts from Node.js via Child Processes
If you’re working in a Node.js environment (not a browser), you can directly spawn a Python process to run your lexer/parser, pass arguments, and capture output.
How to implement it:
- Write a Python wrapper script that reads input from command line arguments, calls your functions, and prints JSON output.
- Use Node.js’s
child_process.spawnto run the script, pass data, and parse the result.
Example Python wrapper (lang_processor.py):
import sys import json from custom_lang import my_lexer, my_parser def main(): # Read input from Node.js (passed as JSON string) input_args = json.loads(sys.argv[1]) action = input_args["action"] text = input_args["text"] try: if action == "lex": result = my_lexer(text) elif action == "parse": result = my_parser(text) else: result = {"error": "Invalid action. Use 'lex' or 'parse'."} except Exception as e: result = {"error": str(e)} # Print result as JSON (Node.js will read this) print(json.dumps(result)) sys.stdout.flush() if __name__ == "__main__": main()
Example Node.js code:
const { spawn } = require('child_process'); const path = require('path'); async function callPythonFunction(action, text) { return new Promise((resolve, reject) => { // Spawn Python process with arguments const pythonProc = spawn('python', [ path.join(__dirname, 'lang_processor.py'), JSON.stringify({ action, text }) ]); let output = ''; let error = ''; // Capture stdout (Python's print output) pythonProc.stdout.on('data', (data) => { output += data.toString(); }); // Capture stderr (Python errors) pythonProc.stderr.on('data', (data) => { error += data.toString(); }); // Handle process exit pythonProc.on('close', (code) => { if (code !== 0) { reject(new Error(`Python process exited with code ${code}: ${error}`)); return; } try { const result = JSON.parse(output); resolve(result); } catch (parseErr) { reject(new Error(`Failed to parse Python output: ${parseErr.message}`)); } }); }); } // Usage callPythonFunction('lex', 'let x = 10') .then(result => console.log("Lexer result:", result)) .catch(err => console.error("Error:", err));
Pros & Cons:
- ✅ No API server needed, direct process communication
- ✅ Native Python performance
- ❌ Only works in Node.js (not browser)
- ❌ Dependent on the system having Python installed and configured correctly
Which Option Should You Choose?
- Browser-only apps: Go with Pyodide.
- Performance-critical apps or existing backends: Build a Python API.
- Node.js backend workflows: Use child processes.
内容的提问来源于stack exchange,提问作者Shardul Nalegave

