Zero-dependency polyglot code execution — run 23 languages from Python
Project description
⚡ Zero-dependency polyglot code execution
Run code in 23 languages from a single Python import — no pip dependencies required.
from polyrun import Rust, Node, Go, Python, Bash, Julia, Zig
result = Rust.run('fn main() { println!("Hello from Rust! ⚡"); }')
print(result.text()) # Hello from Rust! ⚡
⚡ Supported languages (23)
| # | Language | Import | Binary needed | Type |
|---|---|---|---|---|
| 1 | Node.js / JavaScript | Node, JS |
node |
Interpreted |
| 2 | Python | Python |
python3 |
Interpreted |
| 3 | Bash | Bash |
bash |
Interpreted |
| 4 | Ruby | Ruby |
ruby |
Interpreted |
| 5 | PHP | PHP |
php |
Interpreted |
| 6 | Perl | Perl |
perl |
Interpreted |
| 7 | Lua | Lua |
lua |
Interpreted |
| 8 | R | R |
Rscript |
Interpreted |
| 9 | TypeScript | TypeScript, TS |
tsx / ts-node / npx |
Transpiled |
| 10 | Go | Go |
go |
Compiled |
| 11 | Rust | Rust |
rustc |
Compiled |
| 12 | C | C |
gcc |
Compiled |
| 13 | C++ | Cpp |
g++ |
Compiled |
| 14 | Java | Java |
javac + java |
Compiled |
| 15 | Kotlin | Kotlin |
kotlinc + java |
Compiled to JAR |
| 16 | Swift | Swift |
swift |
Interpreted |
| 17 | Haskell | Haskell |
runghc |
Interpreted |
| 18 | Elixir | Elixir |
elixir |
Interpreted |
| 19 | Dart | Dart |
dart |
JIT |
| 20 | Julia | Julia |
julia |
JIT |
| 21 | Groovy | Groovy |
groovy |
Interpreted |
| 22 | Zig | Zig |
zig |
Compiled |
No pip dependencies. Uses only Python's stdlib:
subprocess,tempfile,shutil,json. Language runtimes must be installed separately and on yourPATH.
⚡ Installation
pip install polyrun
From source:
git clone https://github.com/og-py3/Polyrun.git
cd Polyrun
pip install -e .
⚡ Quick start
Hello world in every language
from polyrun import (
Node, Python, Ruby, PHP, Bash, Perl, Lua, R, TypeScript,
Go, Rust, C, Cpp, Java, Kotlin, Swift, Haskell,
Elixir, Dart, Julia, Groovy, Zig,
)
Node.run("console.log('⚡ node')")
Python.run("print('⚡ python')")
Ruby.run("puts '⚡ ruby'")
PHP.run("echo '⚡ php';")
Bash.run("echo '⚡ bash'")
Perl.run("print '⚡ perl\n';")
Lua.run("print('⚡ lua')")
R.run("cat('⚡ R\n')")
TypeScript.run('const x: string = "⚡ typescript"; console.log(x);')
Go.run('package main\nimport "fmt"\nfunc main(){fmt.Println("⚡ go")}')
Rust.run('fn main(){println!("⚡ rust");}')
C.run('#include <stdio.h>\nint main(){puts("⚡ c");return 0;}')
Cpp.run('#include <iostream>\nint main(){std::cout<<"⚡ cpp"<<std::endl;}')
Java.run('public class Hi{public static void main(String[] a){System.out.println("⚡ java");}}')
Kotlin.run('fun main(){println("⚡ kotlin")}')
Swift.run('print("⚡ swift")')
Haskell.run('main :: IO ()\nmain = putStrLn "⚡ haskell"')
Elixir.run('IO.puts("⚡ elixir")')
Dart.run('void main(){print("⚡ dart");}')
Julia.run('println("⚡ julia")')
Groovy.run("println '⚡ groovy'")
Zig.run('const std=@import("std");\npub fn main()!void{try std.io.getStdOut().writer().print("⚡ zig\\n",.{});}')
⚡ RunResult API
result = Python.run("print('hello')")
result.text() # "hello" — stripped stdout
result.lines() # ["hello"] — stdout as list
result.json() # parse stdout as JSON
result.ok() # True — returncode == 0
result.stdout # raw stdout string
result.stderr # raw stderr string
result.returncode # integer exit code
result.language # "Python"
⚡ stdin passthrough
result = Node.run(
"process.stdin.resume(); let d=''; "
"process.stdin.on('data', c => d += c); "
"process.stdin.on('end', () => console.log(d.trim().toUpperCase()));",
input_data="hello world",
)
print(result.text()) # HELLO WORLD
⚡ Environment variables
result = Bash.run("echo $GREETING", env={"GREETING": "⚡ polyrun"})
print(result.text()) # ⚡ polyrun
⚡ Error handling
from polyrun import Rust
from polyrun.exceptions import CompilationError, PolyRuntimeError, LanguageNotFoundError
try:
Rust.run("fn main() { this_wont_compile }")
except CompilationError as e:
print(f"❌ Compile error [{e.language}]: {e.stderr}")
except PolyRuntimeError as e:
print(f"❌ Runtime error [{e.language}] exit {e.returncode}: {e.stderr}")
except LanguageNotFoundError as e:
print(f"❌ Install {e.binary} to use {e.language}")
| Exception | When raised | Attributes |
|---|---|---|
CompilationError |
Compiler exits non-zero | .language, .stderr |
PolyRuntimeError |
Program exits non-zero | .language, .stderr, .returncode |
LanguageNotFoundError |
Binary not on PATH | .language, .binary |
RuntimeErroris kept as an alias forPolyRuntimeErrorfor backwards compatibility.
⚡ Pipeline — chain languages
from polyrun import Node, Python, Bash
from polyrun.pipeline import Pipeline
result = (
Pipeline()
.then(Node, "console.log(JSON.stringify({value: 21}))")
.then(Python, "import sys,json; d=json.load(sys.stdin); print(d['value']*2)")
.then(Bash, 'read n; echo "⚡ The answer is $n"')
.run()
)
print(result.text()) # ⚡ The answer is 42
⚡ Bridge — JSON data exchange
from polyrun import Go
from polyrun.pipeline import Bridge
code = """
package main
import ("encoding/json";"fmt";"os")
func main() {
var d map[string]interface{}
json.NewDecoder(os.Stdin).Decode(&d)
nums := d["numbers"].([]interface{})
sum := 0.0
for _, n := range nums { sum += n.(float64) }
fmt.Println(sum)
}
"""
result = Bridge.send(Go, code, data={"numbers": [1,2,3,4,5]})
print(result.text()) # 15
⚡ Check installed languages
from polyrun.detect import check, available
check() # prints ⚡ Polyrun availability table
⚡ Polyrun — language availability (8/22 installed)
──────────────────────────────────────────────────
✅ Node.js / JavaScript
✅ Python
❌ Java
✅ Rust
...
⚡ Architecture
┌──────────────────────────────────────────────────────────┐
│ Your Python code │
│ from polyrun import Rust, Node, Go, Julia │
│ result = Rust.run(code, input_data="hello") │
└────────────────────────┬─────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────┐
│ ⚡ polyrun │
│ BaseRunner — 23 language runners │
│ Pipeline — stdout → stdin chaining │
│ Bridge — JSON encode/decode │
│ detect — shutil.which availability checks │
│ exceptions — CompilationError / PolyRuntimeError / … │
└────────────────────────┬─────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────┐
│ subprocess + tempfiles (isolated per run) │
│ 1. Write code → temp file │
│ 2. Compile if needed (gcc, rustc, javac, kotlinc, zig) │
│ 3. Run via subprocess, capture stdout/stderr │
│ 4. Return RunResult, clean up temp dir │
└──────────────────────────────────────────────────────────┘
⚡ Project structure
polyrun/
├── polyrun/
│ ├── __init__.py # 23 runner singletons
│ ├── base.py # BaseRunner + RunResult
│ ├── pipeline.py # Pipeline + Bridge
│ ├── detect.py # ⚡ availability report
│ ├── exceptions.py # CompilationError / PolyRuntimeError / LanguageNotFoundError
│ ├── py.typed # PEP 561 marker
│ └── runners/ # 22 runner modules
│ ├── node.py java.py c.py cpp.py rust.py go.py
│ ├── python.py ruby.py php.py bash.py typescript.py perl.py
│ ├── lua.py r.py kotlin.py haskell.py swift.py elixir.py
│ └── dart.py julia.py groovy.py zig.py
├── tests/
│ ├── conftest.py # auto-skip for missing runtimes
│ ├── test_base.py
│ ├── test_detect.py
│ ├── test_exceptions.py
│ ├── test_pipeline.py
│ ├── test_runners_interpreted.py # Node, Python, Ruby, PHP, Bash, Perl, Lua, R
│ ├── test_runners_compiled.py # C, C++, Rust, Go, Java, Kotlin, Haskell, Swift, Dart, Zig
│ └── test_runners_functional.py # TypeScript, Elixir, Julia, Groovy + cross-language
├── logo.svg
├── demo.py
├── pyproject.toml
├── setup.py
├── CHANGELOG.md
├── CONTRIBUTING.md
└── LICENSE
⚡ Running the tests
pip install pytest pytest-cov
pytest tests/ -v
# With coverage report:
pytest tests/ --cov=polyrun --cov-report=term-missing
# Tests auto-skip for any runtime not installed on your machine.
⚡ Publishing to PyPI
pip install build twine
python -m build
twine upload dist/*
⚡ Contributing
See CONTRIBUTING.md — adding a new language runner takes about 30 lines of code.
License
MIT — see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file polyrun-0.2.0.tar.gz.
File metadata
- Download URL: polyrun-0.2.0.tar.gz
- Upload date:
- Size: 18.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/4.0.1 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.1 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b915568bec5a8c00bba5a5cbd989813c2f67a5f4fc442bce6c202fae68e98bf9
|
|
| MD5 |
99192e4f7f919df832447038466075f9
|
|
| BLAKE2b-256 |
582bb3ab2a06edc1b60f5f931b312f06bde6c7d1ecb045860dc3ffe35acf5432
|
File details
Details for the file polyrun-0.2.0-py3-none-any.whl.
File metadata
- Download URL: polyrun-0.2.0-py3-none-any.whl
- Upload date:
- Size: 29.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/4.0.1 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.1 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5af6b908f55a2c3e6e1b5792ae961a1666ddc92c1f1ced245a9b921c694f2439
|
|
| MD5 |
748358c65fefc658e89c326cd2517683
|
|
| BLAKE2b-256 |
b9005a310ea39edbc5cb0d41d2885bef73b5b7a72d02c57536634fddb64b747d
|