Python distribution for the browser and Node.js based on WebAssembly that enables running Python code with full JavaScript interoperability
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Execute Python code from JavaScript with full control over execution context, globals, and async/await support.
Execute Python code synchronously and return the result of the last expression.
function runPython(
code: string,
options?: {
globals?: PyProxy;
locals?: PyProxy;
filename?: string;
}
): any;Parameters:
code - Python code string to executeoptions.globals - Python dictionary to use as global namespace (default: pyodide.globals)options.locals - Python dictionary to use as local namespace (default: same as globals)options.filename - Filename for traceback display (default: "<exec>")Returns: Result of the last expression, converted to JavaScript
Execute Python code with top-level async/await support.
function runPythonAsync(
code: string,
options?: {
globals?: PyProxy;
locals?: PyProxy;
filename?: string;
}
): Promise<any>;Parameters: Same as runPython
Returns: Promise resolving to the result of the last expression
// Simple expression
const result = pyodide.runPython("2 + 3");
console.log(result); // 5
// Multiple statements
pyodide.runPython(`
import math
x = 10
y = math.sqrt(x)
print(f"Square root of {x} is {y}")
`);// Set variables from JavaScript
pyodide.globals.set("js_value", 42);
const result = pyodide.runPython(`
python_value = js_value * 2
python_value # This becomes the return value
`);
console.log(result); // 84
// Get variables back to JavaScript
const pythonVar = pyodide.globals.get("python_value");
console.log(pythonVar); // 84// Create custom execution context
const customGlobals = pyodide.toPy({
myFunction: (x) => x * 2,
myData: [1, 2, 3, 4, 5]
});
const result = pyodide.runPython(`
# Use custom globals
processed = [myFunction(x) for x in myData]
sum(processed)
`, { globals: customGlobals });
console.log(result); // 30const result = pyodide.runPython(`
def divide(a, b):
return a / b
divide(10, 0) # This will cause an error
`, { filename: "my_script.py" });
// Error traceback will show "my_script.py" as the filename// Top-level await in Python
const result = await pyodide.runPythonAsync(`
import asyncio
async def fetch_data():
await asyncio.sleep(0.1)
return {"message": "Hello from async Python!"}
data = await fetch_data()
data
`);
console.log(result); // { message: "Hello from async Python!" }// Register async JavaScript function
pyodide.globals.set("fetchData", async (url) => {
const response = await fetch(url);
return await response.json();
});
const result = await pyodide.runPythonAsync(`
# Call async JavaScript function from Python
from js import fetchData
data = await fetchData("https://api.example.com/data")
data
`);try {
pyodide.runPython(`
undefined_variable # This will raise NameError
`);
} catch (error) {
console.error("Python error:", error.message);
// Error includes Python traceback
}
// Async error handling
try {
await pyodide.runPythonAsync(`
async def failing_function():
raise ValueError("Something went wrong")
await failing_function()
`);
} catch (error) {
console.error("Async Python error:", error.message);
}// Return various Python types
const results = {
number: pyodide.runPython("42"),
string: pyodide.runPython("'Hello World'"),
list: pyodide.runPython("[1, 2, 3, 4, 5]"),
dict: pyodide.runPython("{'key': 'value', 'number': 123}"),
none: pyodide.runPython("None"),
boolean: pyodide.runPython("True")
};
console.log(results);
// {
// number: 42,
// string: "Hello World",
// list: [1, 2, 3, 4, 5],
// dict: {key: "value", number: 123},
// none: null,
// boolean: true
// }// Return complex Python objects
const pandas_df = pyodide.runPython(`
import pandas as pd
pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
`);
// pandas_df is a PyProxy object
console.log(pandas_df.toString()); // String representation
console.log(pandas_df.shape); // [3, 2]
// Call methods on PyProxy
const sum_result = pandas_df.sum();
console.log(sum_result.toJs()); // Convert to JavaScript object// Create isolated execution context
const isolatedGlobals = pyodide.toPy({});
const isolatedLocals = pyodide.toPy({});
pyodide.runPython(`
secret_value = "this won't leak"
def private_function():
return "private"
`, {
globals: isolatedGlobals,
locals: isolatedLocals
});
// secret_value is not in main globals
console.log(pyodide.globals.has("secret_value")); // false
// But available in isolated context
console.log(isolatedGlobals.get("secret_value")); // "this won't leak"const result = pyodide.runPython(`
class Calculator:
def __init__(self):
self.history = []
def add(self, a, b):
result = a + b
self.history.append(f"{a} + {b} = {result}")
return result
def get_history(self):
return self.history
calc = Calculator()
calc.add(5, 3)
calc.add(10, 7)
calc.get_history()
`);
console.log(result); // ["5 + 3 = 8", "10 + 7 = 17"]// Expression (returns value)
const expr_result = pyodide.runPython("2 + 3");
console.log(expr_result); // 5
// Statement (returns undefined)
const stmt_result = pyodide.runPython("x = 2 + 3");
console.log(stmt_result); // undefined
// Mixed (returns last expression)
const mixed_result = pyodide.runPython(`
x = 10
y = 20
x + y # This expression is returned
`);
console.log(mixed_result); // 30
// Suppress return with semicolon
const suppressed = pyodide.runPython("2 + 3;");
console.log(suppressed); // undefinedInstall with Tessl CLI
npx tessl i tessl/npm-pyodide