Limitations of the "file" protocol

Frequently asked questions

Syntax, keywords and built-in functions

Standard distribution

import implementation

Brython packages

Browser interface

Introduction - DOM API
Creating a document
Accessing elements
Attributes, properties and methods

Mouse events
Keyboard events
Focus events
Drag events

Query string

Interactions with Javascript

Brython-specific built-in modules




Working with Brython

Execution options
Testing and debugging
Deploying an application


Hello world !
Insert content in an element
HTML markup (bold,italic...)
HTML table
Bind and unbind events
Handle options in a SELECT
Drag and drop
Get the content of an element
Read the content of a file
Store objects locally
Example of onmouseover

Frequently asked questions

Q : what does "Brython" mean ?

A : Browser Python. It's also the Welsh word for "brittonic-speaking Celt".

Q : which browsers support Brython ?

A : all modern browsers, including on smartphones. The generated Javascript purposely avoids using new syntax until it is supported by most browsers.

Note that performance is usually better (sometimes much better) with Firefox than with Chrome.

Q : what is the performance of Brython compared to CPython ?

R : this page compares the execution time of a number of elementary operations between the latest version of Brython on Firefox and CPython. The results vary depending on operations, but overall the order of magnitude is the same.

The Brython repository includes a script, at address localhost:8000/speed, that compares the speed of Brython and CPython on the local machine for a variety of elementary operations.

Q : what is the performance of Brython compared to Javascript ?

A : compared to Javascript, the ratio is naturally very different from one program to another. A Javascript console is provided in the distribution or on the Brython site, it can be used to measure the execution time of a Javascript program compared to its equivalent in Python in the editor (unchecking the "debug" box)

The difference is due to two factors :

  • the time to translate Python into Javascript, on the fly in the browser. To give an idea, the module datetime (2130 lines of Python code) is parsed and converted to Javascript in 0,5 second on an ordinary PC
  • JavaScript code generated by Brython must be compliant with the specifications of Python, including the dynamic nature of the search attributes, which leads to unoptimized Javascript code

Q : I see a lot of 404 errors in the browser console when I run Brython scripts, why is that ?

A : this is because of the way Brython implements the "import" mechanism. When a script has to import module X, Brython searches for a file or a package in different directories : the standard library (directory libs for Javascript modules, Lib for Python modules), the directory Lib/site-packages, the directory of current page. For that, Ajax calls are sent to the matching urls; if the file is not found, the 404 error message is written in the browser console, but the error is caught by Brython which goes on searching until it finds the module, or raises ImportError if all paths have been tried with no result

Q : why does this message show in the browser console : "Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help" ?

A : this is also related to imports, or to file reading. To achieve these operations, Brython uses blocking Ajax calls : an imported module must be loaded before it can be used. Browser vendors should normally not remove blocking calls any time soon.

Q : is it possible to precompile Brython scripts, in order to reduce execution time ?

A : Brython is designed to be as simple to run as Javascript : put Python code in a <script> section of an HTML page, load the page, edit the code, reload the page, etc. It is not like other projects where the Python code is translated to Javascript by a CPython script, so for each modification you have to run this script before reloading the page.

Another reason why it is a not a good idea to precompile Brython is that the generated code is typically 10 times bigger than the original Python source - this is the price to pay for compliance with the language specification. The page would take longer to load, and we haven't found that this would be faster than compiling on the fly.

However, since version 3.6.0, a precompiled version of the scripts in the standard library is stored in an indexedDB database attached to the browser where the code is executed. The compilation is performed the first time a script is imported, or if the Brython version changed since the last compilation. This improves dramatically the imports loading time.

Q : I am trying to import a module from the Brython standard distribution and I get an error message, why ?

R : the most likely reason is that the script brython_stdlib.js has not been included in the page.

Q : can I import all the modules / packages that run with CPython ?

R : no, only those that are completely written in Python. The programs that use extensions written in C are not supported. For instance, Numpy, Matplotlib, Pandas cannot work with Brython.

It is the same for modules / packages that call primitives of the operating system that are not available in the browser context: for instance requests, which uses the IP stack to execute HTTP requests to arbitrary urls, when a browser can only send Ajax requests to the same domain, or the the (rare) sites that support cross-origin requests.

Q : why use the operator <= to build the tree of DOM elements ? This is not pythonic !

A : Python has no built-in structure to manipulate trees, ie to add "child" or "sibling" nodes to a tree node. For these operations, functions can be used ; the syntax proposed by Brython is to use operators : this is easier to type (no parenthesis) and more readable

To add a sibling node, the operator + is used.

To add a child, the operator <= was chosen for these reasons :

  • it has the shape of a left arrow ; note that Python function annotations use a new operator -> that was chosen for its arrow shape
  • it can't be confused with "lesser or equal" because a line with document <= elt would be a no-op if it was "lesser or equal", which is always used in a condition or as the return value of a function
  • in Python, <= is used as an operator for sets with a different meaning than "lesser or equal"
  • Python uses the same operator % for very different operations : modulo and string formatting
  • the pathlib module in Python standard library uses the operator / to build file system paths

Anyway, those who are allergic to operator overloading can use the method attach() of DOM elements instead.