Python
Computerwelt.Emulation.Python is a Python implementation in C#: a parser, a bytecode compiler with
scope and name resolution, a stack VM with its own object heap, the built-in types, the built-in
functions, and a subset of the standard library.
It is a port of Monty, which Pydantic built for exactly this job: running code a language model wrote, safely, without a CPython process.
using Computerwelt.Emulation.Python;
var runner = new PythonRunner();
var result = runner.Run("""
rows = [{"id": i, "sq": i * i} for i in range(4)]
for row in rows:
print(row["id"], row["sq"])
""");
Console.WriteLine(result.Stdout);
RunResult
| Member | What it carries |
|---|---|
Succeeded |
whether the program ran to completion |
Stdout, Stderr |
what it printed |
ExitCode |
what sys.exit(n) set, or 0 |
Exception |
the Python exception it raised, if any |
SyntaxError |
the syntax error, if it did not compile |
Traceback |
the traceback as Python would have printed it |
Value |
the value of the last expression |
Globals |
the globals the program ended with |
A failure is a value here, not a .NET exception. That is what lets a host feed a traceback back to a model as ordinary text.
Configuring a run
var runner = new PythonRunner(ExecutionLimits.Strict)
{
Arguments = { "report", "--json" }, // sys.argv
StandardInput = "42\n", // sys.stdin
};
runner.Variables["threshold"] = new PyInt(10); // a pre-set global
var result = runner.Run(source, fileName: "report.py");
FileSystem and TimeProvider are settable too, so a program's open, os and clock are whatever
the host decided they are. Leave the filesystem unset and the program has none: open raises
OSError, which is an error the script can catch rather than a host exception escaping into it.