2

Good Afternoon from Germany, everybody!

Google Colab and I seem to have divergent opinions on what is possible or not... I just want a way to access the contents of all other cells from within a cell.

My use case is, that I want to POST the contents of a current Colab Notebook to an external server for grading with minimal user interaction (just running the cell).

So my question is: Is there a way to access the code cells of a Colab NB programmatically?

I saw this answer for Jupyter NB, but it does not work in Google Colab as the Jupyter JS-Variable is not available. The variable google.colab seems to not provide the same functionality, or am I missing something?

Google Colab seems to sandbox each cell in its one iframe, so I cannot query the contents of other cells via JS:

    %%js
    document.getElementsByClassName('cell')

When run in a cell this just leads to an empty HTMLCollection, when run in the Developer Tools of my browser I get the correct results.

Am I missing something here? Is there a way to escape the sandbox or access the current NB contents within a Python cell?

Thanks in Advance for your help!

hno2
  • 97
  • 2
  • 16

2 Answers2

4

Sure, here's a complete example: https://colab.research.google.com/drive/1mXuyMsPEXFU4ik9EGLBiWUuNfztf7J6_

The key bit is this:

# Obtain the notebook JSON as a string
from google.colab import _message
notebook_json_string = _message.blocking_request('get_ipynb', request='', timeout_sec=5)

Reproducing the executed example from the notebook:

enter image description here

hno2
  • 97
  • 2
  • 16
Bob Smith
  • 36,107
  • 11
  • 98
  • 91
  • Awesome, exactly what I was looking for! But why is there no documentation for this (or was I too stupid) to find this? [`blocking_request`](https://github.com/googlecolab/colabtools/blob/eb61c58715be10b0334af0e6f756105f0263cac7/google/colab/_message.py#L155) has no documentation for what `request_types` are available – hno2 Jun 28 '21 at 10:58
  • Also I think you missed one `_` in your link. – hno2 Jun 28 '21 at 10:58
  • 1
    Thanks for the link fix edit. The `_message` module isn't part of the public API, so it's easy to miss without reading the [code](https://github.com/googlecolab/colabtools/blob/main/google/colab/_message.py). But, it work as you'd hope. – Bob Smith Jun 28 '21 at 16:07
  • Thanks for sharing! It's so useful! – Milo Chen May 06 '23 at 08:42
1

Probably not an ideal solution - but one option may be to read the notebook file directly instead of trying to access the cells internally. The following code mounts the user's google drive in the notebook so that you can read its contents as a file:

from pathlib import Path
from google.colab import drive

# Mount the users google drive into the notebook (takes the
# user to an auth flow for access).
drive.mount('/content/drive')

# Read the contents of the notebook file to POST to grading server.
base = Path('/content/drive/MyDrive/Colab Notebooks')
notebook_path = 'notebook.ipynb'
with open(base / notebook_path) as infile:
  notebook_contents = infile.read()

Finding the path of the notebook seems to be tricky, but if it has a standard name you could search for it using base.rpath('*.ipynb') and present the user with some options of files to submit.

Simon Bowly
  • 1,003
  • 5
  • 10
  • Thanks Simon, I was really hoping for a more direct solution, e.g. via JS. – hno2 Jun 27 '21 at 15:39
  • 1
    I can also add to your solution, you can get the name of the current file via: `unquote(get('http://172.28.0.2:9000/api/sessions').json()[0]['name']) ` Or get the drive file id (`path`) via the session, too! – hno2 Jun 27 '21 at 15:39