A JavaScript library that runs Python 3 code on web browsers based on Brython.
Brython is designed to replace JavaScript in the Web; it allows you to use Python 3 instead of JavaScript as the scripting language for your web application. Brython does that by translating Python code into the equivalent JavaScript code.
However, if you want to run user-written Python code in your web application, it's not so simple to do so. Use Brython Runner for that.
See how Pythonpad runs user-written Python 3 code on the browser with Brython Runner; it supports input()
, time.sleep(x)
, and file system with local .py
import feature.
If you need a simple example, see our demo page and see brython-runner
in action.
$ npm install brython-runner
The simple way to use it in a browser:
<script src="lib/brython-runner.bundle.js"></script>
<script>
async function runPythonCode() {
const runner = new BrythonRunner({
stdout: {
write(content) {
console.log('StdOut: ' + content);
},
flush() {},
},
stderr: {
write(content) {
console.error('StdErr: ' + content);
},
flush() {},
},
stdin: {
async readline() {
var userInput = prompt();
console.log('Received StdIn: ' + userInput);
return userInput;
},
}
});
console.log('Run Code:');
await runner.runCode('print("hello world")\nprint("from Brython Runner")');
console.log('Done.');
}
runPythonCode();
</script>
You can directly require the module if you're using webpack to bundle your project. For example:
var BrythonRunner = require('brython-runner/lib/brython-runner.js').default;
or with import
syntax:
import BrythonRunner from 'brython-runner/lib/brython-runner.js';
The core source of BrythonRunner
uses raw-loader for importing JavaScript and Python scripts as String values. If your working in non-webpack CommonJS environment, be sure to handle import statements with prefix !!raw-loader!
in the source.
For example:
import stdioSrc from '!!raw-loader!../scripts/stdio.py'
import sleepSrc from '!!raw-loader!../scripts/sleep.py'
import fileioSrc from '!!raw-loader!../scripts/fileio.py'
const runner = new BrythonRunner({
stdout: {
write(content) {
console.log('StdOut: ' + content);
},
flush() {},
},
stderr: {
write(content) {
console.error('StdErr: ' + content);
},
flush() {},
},
stdin: {
async readline() {
var userInput = prompt();
console.log('Received StdIn: ' + userInput);
return userInput;
},
}
});
await runner.runCode('print("hello world")');
Set debug
option to explicitly set the debug level for Brython. See this page from the Brython website for more information.
- 0 (default) : no debugging. Use this when the application is debugged, it slightly speeds up execution
- 1 : error messages are printed in the browser console (or to the output stream specified by sys.stderr)
- 2 : the translation of Python code into Javascript code is printed in the console
- 10 : the translation of Python code and of the imported modules is printed in the console
const runner = new BrythonRunner({ debug: 10 });
Use onInit
option to set a function that is called after the web worker initialization.
const runner = new BrythonRunner({
onInit() {
console.log('Runner web worker is ready!');
},
});
Brython Runner requires a hanger server to support Python's input()
function in the web worker environment.
A Brython Runner instance will use the hanger server instance served for the Pythonpad service on default settings.
However, you can serve your own hanger server and provide the URL to the server as hangerUrl
option.
const runner = new BrythonRunner({
hangerUrl: 'https://www.pythonpad.co/hanger',
});
An aiohttp-based implementation of a hanger server is available in this repository: Brython Runner StdIn Hanger. Go check out detailed information on how standard input works in the Brython Runner.
Use runCodeWithFiles
method with onFileUpdate
option to provide files and directories for the Python code.
const files = {
'hello.py': {
'type': 'text',
'body': 'print("hello world")',
},
'data/': {
'type': 'dir',
'body': '',
},
'data/image.gif': {
'type': 'base64',
'body': 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
},
'main.py': {
'type': 'text',
'body': 'import hello\nf = open("data/image.gif", "rb")\nf.close()',
}
};
const runner = new BrythonRunner({
onFileUpdate(filename, data) {
files[filename].type = data.type;
files[filename].body = data.body;
},
});
runner.runCodeWithFiles(files['main.py'].body, files);
BrythonRunner.runCodeWithFiles(code, files)
method runs Python code
with given files
. Files must be provided as a JavaScript object that contains each file or directory as a key-value pair.
An object key for a file or a folder represents a path to the file from a virtual current working directory. A path for a file should be normalized (os.path.normpath(path) === path
) and should be inside the current working directory (e.g., ../file.txt
is not allowed).
If a path is for a folder, it should have a trailing slash added to a normalized path. See the data/
folder in the example code.
A value for a file or a folder should be a JavaScript object that contains values for the keys: type
and body
.
If it is a folder, type
should be 'dir'
and body
should be an empty string (''
). If it is a file, two types are available: 'text'
and 'base64'
.
Files with 'text'
type should have string type content of the file as the body
value. Files with 'base64'
type should have the content encoded in base64 as the body
value.
If the files are edited while running the code, a function given as onFileUpdate
option is called. The path of the edited file is given as the first parameter (filename
) and the data object with type
and body
values is given as the second parameter (data
).
To serve the exmaple web page for development, run:
$ npm dev
Check out http://localhost:4000 on your web browser to see the example web page.
To build the library, run:
$ npm build