code-playpad

Several files: modules and packages

A widget can hold more than one file. They are written into Pyodide's filesystem before the run, next to the entry point and on sys.path, so ordinary import works — flat modules, packages with __init__.py, and plain data files you open(). Pick a file with the tabs; marks the one Run executes.

A package, a module, and an entry point

from geometry import Circle, Rectangle from report import table shapes = [Circle(1), Rectangle(2, 3), Circle(0.5)] print(table(shapes)) print() print("__name__ here is", __name__) sum(s.area() for s in shapes) """A real package: geometry/__init__.py re-exports the shape classes.""" from .shapes import Circle, Rectangle __all__ = ["Circle", "Rectangle"] from dataclasses import dataclass from math import pi @dataclass class Circle: radius: float def area(self) -> float: return pi * self.radius ** 2 @dataclass class Rectangle: width: float height: float def area(self) -> float: return self.width * self.height def table(shapes): rows = [f"{type(s).__name__:<10} {s.area():8.3f}" for s in shapes] total = sum(s.area() for s in shapes) rows.append(f"{'total':<10} {total:8.3f}") return "\n".join(rows)
Edit geometry/shapes.py — say, make Rectangle.area return 0 — and press Run. The module cache is cleared between runs, so the edit takes effect immediately instead of Python serving the copy it imported last time.

Tracebacks name the real file

The entry point is executed under its own path, so a failure inside a package points at geometry/shapes.py and its line number — not at <exec>.

from geometry.shapes import Circle print("about to fail") Circle(-1).area() from math import pi class Circle: def __init__(self, radius): self.radius = radius def area(self): if self.radius < 0: raise ValueError(f"radius must be positive, got {self.radius}") return pi * self.radius ** 2

Not just Python files

Anything in the file list lands on disk, so open(), the csv module, and relative paths behave normally. The working directory is the widget's own folder.

import csv from pathlib import Path rows = list(csv.DictReader(Path("stock.csv").open())) for row in rows: print(f"{row['item']:<8} {int(row['qty']):>4}") print("---") print("total", sum(int(r["qty"]) for r in rows)) item,qty bolts,120 nuts,340 washers,75
Files are per-widget but the runtime is still shared: all three playgrounds on this page use the same Worker, and each run rewrites its own file set first. Completed: