Comment on page

Python cells

Creating a Python cell

Create a Python cell by either:
  • Using the Y keyboard shortcut to place a new cell
  • Selecting the Python cell option from the control bar
  • Selecting the Add Python cell option when referencing a cell from the + icon that appears when the cell is selected.

How Python cells work

Python cells work very similarly to SQL cells, consisting of a text input area and an output area. Python cells are reactive just like all other cells, and their relationships are indicated by the same connector lines.
In Count, Python cells are executed locally in your browser using a version of Python that has been developed to work on the web. When you first execute a Python cell, the Python environment is downloaded and started, which may take a few seconds the first time.

Referencing other cells using the cells variable

In Python cells, there is a special global cells variable that contains the results of other cells formatted as pandas DataFrames. Access cell results using keys or attributes on this object:

Referencing Python variables

All variables defined at the root scope of a Python cell are global, and can be accessed in any other Python cell. Count will detect relationships between Python cells based on the variables they reference, and add connector lines automatically.
Because Count executes cells reactively, it's possible to accidentally create circular dependencies. In this case, like other cells, Python cells will display an error and refuse to execute:

Referencing Python cells from DuckDB

The last expression in a Python cell is special, and becomes the single output of that cell. If this output can be represented as a table, it can be queried by local DuckDB cells too:

Python cell outputs

As Python is a more expressive language than SQL, it is able to output more data types:
  • Table output - if the final expression of the cell is representable as a table
  • Image output - if the final expression of the cell is a PNG-formatted image bytes object
  • Logs output - if the cell has printed anything during its execution
The output type defaults to Automatic, which can be overridden from the Output type button above the cell.


Because Python cells work just like any other cell, you can use control cells to add interactivity to any Python cell. In the example below, the parameters of a plot are adjustable using control cells:
An example of adding interactivity to a Python cell

Python modules

To load a module, just import it as usual and Count will attempt to automatically download it and make it available. The first import of a new package may take a few seconds for this reason.
As your Python code is running in your browser, there are some restrictions on the modules that you can load. Available packages include:
  • pandas
  • numpy
  • matplotlib
  • scipy
  • scikit-learn
  • Any module hosted on PyPi that is written in pure Python
  • Any module specifically built for running in the browser. Many popular data-focussed modules are already supported, with more on the way. See the full list here.

Performing network requests

Unfortunately the popular requests module is not currently supported in Count. It is possible to make network requests from a Python cell using a similar library designed to mimic the most common features of requests :
from count_requests import post, get
req1 = post('<some URL>', json={ 'key': 'value' })
req2 = get('<some URL>', params={ 'key': 'value' }, headers={ 'a': 'b' })
res1 = await req1.json()
res2 = await req2.text()
For more documentation on this module, type help(count_requests) from a Python cell, or read the docstrings available in cell autocomplete suggestions.
Network requests are performed from a Count server, and the result returned back to your browser. Maximum request payload limits apply, so network requests will fail if they are too large.

Using secrets

If your project has any secrets configured, it is possible to use these secrets in network requests. Just format the secret name (not value!) using the secret method exposed by the count_requests module. The result of this method is just another string which looks like $$abc123$$, so it can be used in other places a string is expected. For example:
from count_requests import post, secret
req = post('<some URL>', headers={ 'Authorization': f"Bearer {secret('token')}" )
There are some security considerations to note when using secrets in Python cells:
  • Secrets can only be used in network requests.
  • Secret values are inserted into the network request once it arrives at a Count server, and then sent to the URL specified in the request.
  • Secret values are not accessible from the Count app regardless of your permission level.
  • If you grant edit access to a canvas, you should assume that the editor will be able to access any secret you have defined by, for example, sending it to a URL that they control.
  • You should never directly enter a secret value into the text of a Python cell, as it will be visible to all viewers of that canvas, even if the cell input is hidden.


What order do my Python cells run in?

Unlike in a Jupyter notebook where cells execute top-to-bottom, in Count your Python cells execute in DAG order, just like SQL cells.
When opening a canvas containing Python cells, Count will:
  • Analyse all of the Python code and look for variable definitions and references.
  • Draw arrows between cells if we’ve detected that variables defined in one cell are referenced in another.
  • Download all of the imported modules and perform all of the imports.
  • Perhaps wait for any SQL cells to finish executing if any Python cells depend on them.
  • Execute the Python cells in order based on which variables they define.
Why does my imported Jupyter notebook not execute as I expect?
When importing a Jupyter notebook, a common pitfall is to have variables defined multiple times in different cells. If this happens, the cells in Count may not execute in the order you expect (though it will be the same order every time the canvas is opened).
You can always check where Count thinks your variables have been defined by following the cell connector lines to their source:
In this example, cell x2 was executed most recently, and so cell x? takes its value from there.