Note: The Listed platform will permanently shut down December 31, 2026. Your data published on Listed will still be available in your personal Standard Notes account. Learn more

Jupyter SN roundtrip

Jupyter is a great but mostly write once experience, since I tend to figure out an idea and then copy it into a knowledge base. On top of that, I have a ton of code stuff that I'd like to publish just to get it out there. Can we set up roundtrips between Jupyter & Standard Notes?

PS. so this note was a pain to put together: getting markdown-syntax into notes where there's some backtick delimited code blocks, tends to break. and then publishing to listed didn't work so well; probably the best approach is for a note to start in Jupyter, convert to SN-ish Markdown, copy into a plain text note, then convert to SN's SuperNote then continue working on the text around the code?

options

  • pandoc (not tested here)
  • jupytext
  • jupyter nbconvert
  • custom convert?

jupytext https://jupytext.readthedocs.io/en/latest/

the "best practice" tool,

$ jupytext --to markdown Untitled.ipynb
$ cat Untitled.md | grep -v '^$'

which generates

---
jupyter:
  jupytext:
    text_representation:
      extension: .md
      format_name: markdown
      format_version: '1.3'
      jupytext_version: 1.16.4
  kernelspec:
    display_name: Python 3 (ipykernel)
    language: python
    name: python3
---
This is a quick test notebook!
## md h2
with some code

import antigravity

but now let's run that:
```python
import antigravity
import numpy as np
np.r_[:42]+1j
for i in range(3):
    %timeit -n2 -r2 10**i
42,

conclusion

that's all for now! bye


but this doesn't include the stream output which I definitely want.

## `jupyter nbconvert`

this is the classic tool, useful to grep out the empty lines,

```javascript
$ jupyter nbconvert --to markdown Untitled.ipynb
$ cat Untitled.md | grep -v '^$'

which generates

This is a quick test notebook!
## md h2
with some code

import antigravity

```python
import antigravity

gio: https://xkcd.com/353/: Operation not supported

import numpy as np
np.r_[:42]+1j

array([ 0.+1.j, 1.+1.j, 2.+1.j, 3.+1.j, 4.+1.j, 5.+1.j, 6.+1.j,
7.+1.j, 8.+1.j, 9.+1.j, 10.+1.j, 11.+1.j, 12.+1.j, 13.+1.j,
14.+1.j, 15.+1.j, 16.+1.j, 17.+1.j, 18.+1.j, 19.+1.j, 20.+1.j,
21.+1.j, 22.+1.j, 23.+1.j, 24.+1.j, 25.+1.j, 26.+1.j, 27.+1.j,
28.+1.j, 29.+1.j, 30.+1.j, 31.+1.j, 32.+1.j, 33.+1.j, 34.+1.j,
35.+1.j, 36.+1.j, 37.+1.j, 38.+1.j, 39.+1.j, 40.+1.j, 41.+1.j])

for i in range(3):
    %timeit -n2 -r2 10**i

402 ns ± 234 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
303 ns ± 143 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
243 ns ± 91.5 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)

conclusion

that's all for now! bye


but I'd like to have the output quoted to keep it visually distinct

## custom renderer?

sounds fancy, buckle up!

```python
import json
with open('Untitled.ipynb', 'r') as fd:
    nb = json.load(fd)

def println(line):
    print(line, end='' if line.endswith('\n') else '\n')

for cell in nb['cells']:
    if cell['cell_type'] == 'markdown':
        for line in cell['source']:
            if line.strip():
                println(line)
    else:
        # print(cell)
        print('```python')
        print(''.join(cell['source']))
        print('```')
        for o in cell['outputs']:
            if o['output_type'] == 'stream':
                for line in o['text']:
                    println(f'> {line}')
            elif o['output_type'] == 'execute_result':
                for line in o['data']['text/plain']:
                    println(f'> {line}')

which generates

This is a quick test notebook!
## md h2
with some code

import antigravity

but now let's run that:
```python
import antigravity

gio: https://xkcd.com/353/: Operation not supported

import numpy as np

np.r_[:42]+1j

> array([ 0.+1.j,  1.+1.j,  2.+1.j,  3.+1.j,  4.+1.j,  5.+1.j,  6.+1.j,
>         7.+1.j,  8.+1.j,  9.+1.j, 10.+1.j, 11.+1.j, 12.+1.j, 13.+1.j,
>        14.+1.j, 15.+1.j, 16.+1.j, 17.+1.j, 18.+1.j, 19.+1.j, 20.+1.j,
>        21.+1.j, 22.+1.j, 23.+1.j, 24.+1.j, 25.+1.j, 26.+1.j, 27.+1.j,
>        28.+1.j, 29.+1.j, 30.+1.j, 31.+1.j, 32.+1.j, 33.+1.j, 34.+1.j,
>        35.+1.j, 36.+1.j, 37.+1.j, 38.+1.j, 39.+1.j, 40.+1.j, 41.+1.j])
```python
for i in range(3):
    %timeit -n2 -r2 10**i
42,

394 ns ± 181 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
382 ns ± 198 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
The slowest run took 5.20 times longer than the fastest. This could mean that an intermediate result is being cached.
826 ns ± 559 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
(42,)

conclusion

that's all for now! bye

rendered version

So SN's version of Markdown isn't exactly like everyone elses ¯_(ツ)_/¯

This is a quick test notebook!

md h2

with some code

import antigravity

but now let’s run that:

import antigravity

gio: https://xkcd.com/353/: Operation not supported

import numpy as np

np.r_[:42]+1j

array([ 0.+1.j, 1.+1.j, 2.+1.j, 3.+1.j, 4.+1.j, 5.+1.j, 6.+1.j,
7.+1.j, 8.+1.j, 9.+1.j, 10.+1.j, 11.+1.j, 12.+1.j, 13.+1.j,
14.+1.j, 15.+1.j, 16.+1.j, 17.+1.j, 18.+1.j, 19.+1.j, 20.+1.j,
21.+1.j, 22.+1.j, 23.+1.j, 24.+1.j, 25.+1.j, 26.+1.j, 27.+1.j,
28.+1.j, 29.+1.j, 30.+1.j, 31.+1.j, 32.+1.j, 33.+1.j, 34.+1.j,
35.+1.j, 36.+1.j, 37.+1.j, 38.+1.j, 39.+1.j, 40.+1.j, 41.+1.j])

for i in range(3):
    %timeit -n2 -r2 10**i
42,

394 ns ± 181 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
382 ns ± 198 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
The slowest run took 5.20 times longer than the fastest. This could mean that an intermediate result is being cached.
826 ns ± 559 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
(42,)

conclusion

that’s all for now! bye


You'll only receive email when they publish something new.

More from maedoc
All posts