marimo-team / marimo

A reactive notebook for Python — run reproducible experiments, execute as a script, deploy as an app, and version with git.
https://marimo.io
Apache License 2.0
6.62k stars 225 forks source link

Convert .py scripts to marimo notebooks #1569

Closed cnrrobertson closed 3 months ago

cnrrobertson commented 4 months ago

Description

Currently marimo convert allows for .md or .ipynb filetypes to convert to notebooks. Unfortunately I've always used .py files with # %% cell delimiters like those outputted by marimo export script file.py for interactive REPL work.

Could marimo convert be extended to also take in these flattened .py files and put them into notebook form? This would make using marimo with my previous work so much easier!

Suggested solution

It seems like it could be as simple as putting some header informatio, replacing any line of # %% with @app.cell\ndef __():, and then ensuring lines are indented correctly. I've already implemented a quick script to do conversion this way.

However, this doesn't account for any variable dependence. So far, it seems like marimo figures out the dependencies when I do this conversion and run the first time, but there may be something more subtle here.

This also doesn't entirely account for other kinds of cells like # %% [markdown].

Alternative

No response

Additional context

No response

akshayka commented 4 months ago

However, this doesn't account for any variable dependence. So far, it seems like marimo figures out the dependencies when I do this conversion and run the first time, but there may be something more subtle here.

Yea, you're right the dependencies are just for readability. marimo can fill them in automatically.

I wonder if there's a tool that converts .py scripts to ipynb files? If so, then you could use marimo convert

akshayka commented 4 months ago

@cnrrobertson According to an SO post, you can use jupytext to go from .py script to ipynb: https://stackoverflow.com/a/55920098

cnrrobertson commented 3 months ago

Ah you're right! That works great. Thanks for the help!

I'd say this can be closed now, but I'll let you guys make the call in case this is something you'll want to include in Marimo at some point.

mscolnick commented 3 months ago

Yea, we can close this. @cnrrobertson if you have a small snippet that you used in your CLI, would be great to add it here for others.

cnrrobertson commented 3 months ago

Sure thing. Here's the quick and dirty snippet I've been using to go from script to Marimo notebook. So far it has worked pretty well:

#!/opt/homebrew/bin/python3

import sys
filename = sys.argv[1]

with open(filename, 'r') as file:
    lines = file.readlines()

new_lines = [
    "import marimo\n",
    "\n",
    # f'__generated_with = "{__version__}"',
    "app = marimo.App()\n",
    "\n",
    "\n",
    "@app.cell\n",
    "def __():\n",
]

for line in lines:
    if line[:4] == "# %%":
        new_lines.append("    return\n")
        new_lines.append("\n")
        new_lines.append("@app.cell\n")
        new_lines.append("def __():\n")
    elif "__generated_with" in line:
        continue
    elif line == "":
        continue
    elif line == "\n":
        continue
    else:
        new_lines.append("    "+line)

if "return" not in new_lines[-1]:
    new_lines.append("    return\n")

print("".join(new_lines))

Note that it cuts out blank lines.