{"id":13478425,"url":"https://github.com/ipyflow/ipyflow","last_synced_at":"2026-04-02T01:31:02.816Z","repository":{"id":40290326,"uuid":"233903484","full_name":"ipyflow/ipyflow","owner":"ipyflow","description":"A reactive Python kernel for Jupyter notebooks.","archived":false,"fork":false,"pushed_at":"2026-01-16T07:44:18.000Z","size":23733,"stargazers_count":1260,"open_issues_count":36,"forks_count":24,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-01-16T22:12:03.266Z","etag":null,"topics":["dataflow","developer-tools","highlighting","ipyflow","jupyter","jupyter-notebooks","jupyterlab","lineage","nbsafety","notebooks","pypi","python","reactivity","static-analysis","static-code-analysis","tracing"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ipyflow.png","metadata":{"files":{"readme":"README.md","changelog":"HISTORY.rst","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-01-14T18:02:25.000Z","updated_at":"2026-01-16T07:44:22.000Z","dependencies_parsed_at":"2023-10-01T21:27:12.295Z","dependency_job_id":"1683adfa-9f67-401d-9122-b70f02c53411","html_url":"https://github.com/ipyflow/ipyflow","commit_stats":{"total_commits":2078,"total_committers":7,"mean_commits":"296.85714285714283","dds":0.09143407122232916,"last_synced_commit":"02499b1375b26fa9ebe19a80b8c2e98469cd3619"},"previous_names":["nbsafety-project/nbsafety","runtime-jupyter-safety/nbsafety"],"tags_count":183,"template":false,"template_full_name":null,"purl":"pkg:github/ipyflow/ipyflow","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipyflow%2Fipyflow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipyflow%2Fipyflow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipyflow%2Fipyflow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipyflow%2Fipyflow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ipyflow","download_url":"https://codeload.github.com/ipyflow/ipyflow/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipyflow%2Fipyflow/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31293913,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T01:05:07.454Z","status":"ssl_error","status_checked_at":"2026-04-02T00:56:46.496Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dataflow","developer-tools","highlighting","ipyflow","jupyter","jupyter-notebooks","jupyterlab","lineage","nbsafety","notebooks","pypi","python","reactivity","static-analysis","static-code-analysis","tracing"],"created_at":"2024-07-31T16:01:56.810Z","updated_at":"2026-04-02T01:31:02.804Z","avatar_url":"https://github.com/ipyflow.png","language":"Python","readme":"\u003ch1\u003e \u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/ipyflow-logo.png\" width=\"25\"\u003e IPyflow \u003c/h1\u003e\n\n[![](https://github.com/ipyflow/ipyflow/workflows/ipyflow/badge.svg)](https://github.com/ipyflow/ipyflow/actions)\n[![Checked with mypy](http://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![License: BSD3](https://img.shields.io/badge/License-BSD3-maroon.svg)](https://opensource.org/licenses/BSD-3-Clause)\n[![](https://img.shields.io/pypi/v/ipyflow.svg)](https://pypi.org/project/ipyflow)\n![](https://img.shields.io/pypi/pyversions/ipyflow.svg)\n\nTL;DR\n-----\nPrecise reactive Python notebooks for Jupyter[Lab]:\n\n1. `pip install ipyflow`\n2. Pick `Python 3 (ipyflow)` from the launcher or kernel selector.\n3. For each cell execution, the (minimal) set of out-of-sync upstream and\n   downstream cells also re-execute, so that executed cells appear as they\n   would when running the notebook from top-to-bottom.\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/ipyflow-tldr.gif\" /\u003e\n\u003c/p\u003e\n\nAbout\n-----\nIPyflow is a next-generation Python kernel for JupyterLab and Notebook 7 that\ntracks dataflow relationships between symbols and cells during a given\ninteractive session, thereby making it easier to reason about notebook state.\nHere is a\n[video](https://www.youtube.com/watch?v=mZZnDlyKk7g\u0026t=8s)\nof the JupyterCon talk introducing it (and corresponding\n[slides](https://docs.google.com/presentation/d/1D9MSiIkwv7gjRr7jfNYZXki9TfkoUr4Yr-a06i0w_QU)).\n\nIf you'd like to skip the elevator pitch and skip straight to installation /\nactivation instructions jump to [quick start](#quick-start) below; otherwise,\nkeep reading to learn about IPyflow's philosophy and feature set.\n\nGoals\n-----\nIPyflow provides bolt-on reactivity to Jupyter's default Python kernel, ipykernel.\nIt was was designed with the following goals in mind:\n- **Full backwards-compatibility with ipykernel:** IPyflow aims to be a\n  *drop-in replacement* for ipykernel, providing a strict superset of its\n  features.\n- **Precise dependency inference:** IPyflow understands dependencies between\n  cells beyond just simple variables. For example, IPyflow understands when\n  cell `B` depends on cell `A` because of a subscript reference `x[0]`, and is\n  smart enough not to reactively execute cell `B` when some other part of `x`,\n  e.g. `x[1]`, changes. As a result, it limits unnecessary re-execution to a\n  bare minimum.\n- **Fearless execution:** IPyflow attempts to enforce the following invariant:\n  whenever you execute a cell, the resulting output appears as it would if you\n  had performed a \"restart + run all\" operation. The implication is that you\n  can execute basically any cell in the notebook and trust that It Just\n  Works\u003csup\u003eTM\u003c/sup\u003e.\n\n\nQuick Start\n-----------\nTo install, run:\n```bash\npip install ipyflow\n```\n\nTo run an IPyflow kernel, select \"Python 3 (ipyflow)\" from the list of\navailable kernels in the Launcher tab. Similarly, you can switch to / from\nIPyflow from an existing notebook by navigating to the \"Change kernel\" file\nmenu item:\n\nEntrypoint                       |  Kernel Switcher\n:-------------------------------:|:-------------------------------:\n![](https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/ipyflow-launcher.png) | ![](https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/change-kernel-lab.png)\n\n\nFeatures\n--------\n\n\n### Reactive execution model\n\nIPyflow ships with extensions that bring reactivity to JupyterLab and Notebook\n7 by default, similar to execution behavior offered in other notebooks such as\n[Observable](https://observablehq.com/),\n[Pluto.jl](https://github.com/fonsp/Pluto.jl), and\n[Marimo](https://github.com/marimo-team/marimo).\n\nIPyflow's reactivity behaves a little bit differently from the above, however,\nas it was designed to meet the needs of Jupyter users in particular. When you\nexecute cell `C` with IPyflow, `C`'s output, the output of the cells `C`\ndepends on, and the output of the cells that depend on `C` all appear as they\nwould if the notebook were executed from top to bottom (e.g. via \"restart and\nrun-all\"). When you select some cell `C`, all the cells that would re-execute\nwhen `C` is executed have an orange dot next to them, and cells that `C`\ndepends on but that are up-to-date and will not re-execute have purple dots:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/ipyflow-dots.gif\" width=\"400\" /\u003e\n\u003c/p\u003e\n\nThe cell dependency information is persisted to the notebook metadata, so that\nyou can jump to any cell after starting a fresh kernel session, run it, and be\nconfident that the output is what was intended by the notebook author:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/ipyflow-restart.gif\" width=\"400\" /\u003e\n\u003c/p\u003e\n\n\n### Autosave and recovering prior executions\n\nBecause IPyflow peeks at runtime state in order to infer dependencies, it needs\nto keep content of the notebook in sync with the kernel's memory state, even\nacross browser refreshes. As such, IPyflow enables autosave-on-change by\ndefault, so that the kernel state, the notebook UI's in-memory state, and the\nnotebook file on disk are all in sync. If you accidentally overwrite a cell's\noutput that you wanted to keep, e.g. during a reactive execution, and autosave\noverwrites the previous result on disk, fear not! IPyflow provides a library\nutility called `reproduce_cell` to recover the input and output of previous\ncell executions (within a given kernel session):\n\n```python\nfrom ipyflow import reproduce_cell\nreproduce_cell(4, lookback=1)  # to reproduce the previous execution of cell 4\n```\n\nExample:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/reproduce-cell.gif\" width=\"400\" /\u003e\n\u003c/p\u003e\n\n\n### Opting out of reactivity\n\nIf you'd like to temporarily opt out of reactive execution, you can use\nctrl+shift+enter (on Mac, cmd+shift+enter also works) to only execute the cell in question:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/alt-mode-execute.gif\" /\u003e\n\u003c/p\u003e\n\nYou can also run the magic command `%flow mode lazy` in opt out of the\ndefault reactive execution mode (in which case, ctr+shift+enter /\ncmd+shift+enter will switch from being nonreactive to reactive). To reenable\nreactive execution as the default, you can run `%flow mode reactive`:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/reactivity-opt-out.gif\" /\u003e\n\u003c/p\u003e\n\nIf you'd like to prevent the default reactive behavior for every new kernel\nsession, you can add this to your IPython profile (default location typically\nat `~/.ipython/profile_default/ipython_config.py`):\n\n```python\nc = get_config()\nc.ipyflow.exec_mode = \"lazy\"  # defaults to \"reactive\"\n```\n\n\n### In-order and any-order semantics\n\nIPyflow defaults to *in-order* semantics, meaning that, if cell `B` depends on\ncell `A`, then `A` must appear before `B` in the spatial order of the notebook.\nIPyflow doesn't prevent previous cells from referencing data created or updated\nby later cells, but it omits these edges when performing reactive execution.\n\nIn-order semantics, though less flexible, have some desirable properties when\ncompared with any-order semantics, as they encourage cleaner and more\nreproducible notebooks that can more easily be converted to Python scripts\nlater. Now that I may or may not have sold you on in-order semantics, you can\nenable any-order semantics in IPyflow by running the magic command `%flow\ndirection any_order`, and reenable the default in-order semantics using `%flow\ndirection in_order`:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/ipyflow-direction.gif\" /\u003e\n\u003c/p\u003e\n\nYou can also update your IPython profile if you'd like to make any-order\nsemantics the default behavior for new kernel sessions:\n\n```python\nc = get_config()\nc.ipyflow.flow_direction = \"any_order\"  # defaults to \"in_order\"\n```\n\n\n### Execution suggestions and shortcut for resolving inconsistencies\n\nWhenever a cell references updated data, the collapser next to it is given an\norange color (similar to the color for dirty cells), and cells that\n(recursively) depend on it are given a purple collapser color. (An orange input\nwith a purple output just means that the output may be out-of-sync.) When using\nreactive execution, you usually won't see these, since out-of-sync dependent\ncells will be rerun automatically, though you may see them if using\nctrl+shift+enter to temporarily opt out of reactivity, or if you change which\ndata the cell updates (thereby overwriting previous edges between cells).\n\nIf you'd like to let IPyflow fix these up for you, you can press \"Space\" when\nin command mode to automatically resolve all stale or dirty cells. This\noperation may introduce more stale cells, in which case you can continue\npressing \"Space\" until all inconsistencies are resolved, if desired:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/resolve-inconsistencies.gif\" width=\"450\" /\u003e\n\u003c/p\u003e\n\n\n### Memoization\n\nCells that reference Python functions and classes, primitives like integers,\nfloats, strings, as well as numpy arrays, pandas dataframes, and containers\n(lists, dicts, sets, tuples, etc.) thereof can be memoized by IPyflow using the\nspecial `%%memoize` pseudomagic. There's no need to specify the \"inputs\" to the\ncell, as IPyflow will infer these automatically. Memoized cells cache their\nresults in-memory (though disk-backed caches are planned for the future), and\nwill retrieve these cached results (rather than re-running the cell) whenever\nIPyflow detects inputs and cell content identical to that of a previous run:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/ipyflow-memoization.gif\" /\u003e\n\u003c/p\u003e\n\nBy default, `%%memoize` skips all output except potential displayhook output\nfrom the last expression in the cell (when applicable). To skip this too, pass\n`--quiet`, and to include stdout, stderr, and other rich output, pass\n`--verbose`:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/memoize-quiet-verbose.gif\" /\u003e\n\u003c/p\u003e\n\n\n### IPyWidgets integration\n\nIPyflow's reactive execution engine has built-in support for `ipywidgets`,\nallowing widget changes to be propagated across cell boundaries:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/ipywidgets-integration.gif\" width=\"500\" /\u003e\n\u003c/p\u003e\n\nThis functionality can be combined with the `%%memoize` magic to provide near\nreal-time rendering of interactive plots across cells:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/ipywidgets-memoization.gif\" width=\"500\" /\u003e\n\u003c/p\u003e\n\nThis functionality can be paired with other extensions like\n[stickyland](https://github.com/xiaohk/stickyland) to build fully reactive\ndashboards on top of JupyterLab + IPyflow.\n\nFinally, IPyflow also integrates with [mercury](https://github.com/mljar/mercury) widgets as well:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ipyflow/ipyflow/master/img/ipyflow-mercury.gif\" width=\"500\" /\u003e\n\u003c/p\u003e\n\n## State API\n\nIPyflow must understand the underlying execution state at a deep level in\norder to provide its features. It exposes an API for interacting with some of\nthis state, including a `code` function for obtaining the code necessary to\nreconstruct some symbol:\n\n```python\n# Cell 1\nfrom ipyflow import code\n\n# Cell 2\nx = 0\n\n# Cell 3\ny = x + 1\n\n# Cell 4\nprint(code(y))\n\n# Output:\n\"\"\"\n# Cell 2\nx = 0\n\n# Cell 3\ny = x + 1\n\"\"\"\n```\n\nYou can also do this at the cell-level as well using the `slice()` method:\n```python\nfrom ipyflow import cells\nprint(cells(4).slice())\n\n# Output:\n\"\"\"\n# Cell 2\nx = 0\n\n# Cell 3\ny = x + 1\n\n# Cell 4\nprint(code(y))\n\"\"\"\n```\n\nYou can also see the cell (1-indexed) and statement (0-indexed) of when a\nsymbol was last updated with the `timestamp` function:\n\n```python\nfrom ipyflow import timestamp\ntimestamp(y)\n# Timestamp(cell_num=3, stmt_num=0)\n```\n\nTo see dependencies and dependents of a particular symbol, use the `deps` and\n`users` fuctions, respectively:\n\n```python\nfrom ipyflow import deps, users\n\ndeps(y)\n# [\u003cx\u003e]\n\nusers(x)\n# [\u003cy\u003e]\n```\n\nIf you want to elevate a symbol to the representation used internally by\nIPyflow, use the `lift` function (at your own risk, of course):\n\n```python\nfrom ipyflow import lift\n\ny_sym = lift(y)\ny_sym.timestamp\n# Timestamp(cell_num=3, stmt_num=0)\n```\n\nColab, VSCode, and other Interfaces\n-----------------------------------\nReactivity and other frontend features are not yet working in interfaces like\nColab or VSCode, but you can still use IPyflow's dataflow API on these surfaces\nby initializing your notebook session with the following code:\n```\n%pip install ipyflow\n%load_ext ipyflow\n```\n\nCiting\n------\nIPyflow started its life under the name nbsafety, which provided the initial\nsuggestions and slicing functionality.\n\nFor the [execution suggestions](http://www.vldb.org/pvldb/vol14/p1093-macke.pdf):\n```bibtex\n@article{macke2021fine,\n  title={Fine-grained lineage for safer notebook interactions},\n  author={Macke, Stephen and Gong, Hongpu and Lee, Doris Jung-Lin and Head, Andrew and Xin, Doris and Parameswaran, Aditya},\n  journal={Proceedings of the VLDB Endowment},\n  volume={14},\n  number={6},\n  pages={1093--1101},\n  year={2021},\n  publisher={VLDB Endowment}\n}\n```\n\nFor the [dynamic slicer](https://smacke.net/papers/nbslicer.pdf) (used for\nreactivity and for the `code` function, for example):\n```bibtex\n@article{shankar2022bolt,\n  title={Bolt-on, Compact, and Rapid Program Slicing for Notebooks},\n  author={Shankar, Shreya and Macke, Stephen and Chasins, Andrew and Head, Andrew and Parameswaran, Aditya},\n  journal={Proceedings of the VLDB Endowment},\n  volume={15},\n  number={13},\n  pages={4038--4047},\n  year={2022},\n  publisher={VLDB Endowment}\n}\n```\n\nFor anything not covered in the above papers, you can cite the IPyflow repo:\n```bibtex\n@misc{ipyflow,\n  title = {{IPyflow: A Next-Generation, Dataflow-Aware IPython Kernel}},\n  howpublished = {\\url{https://github.com/ipyflow/ipyflow}},\n  year = {2022},\n}\n```\n\nAcknowledgements\n----------------\nIPyflow would not have been possible without the amazing academic collaborators\nlisted on the above papers. Its reactive execution features are inspired by\nthose of other excellent tools like [Hex](https://hex.tech/) notebooks,\n[Pluto.jl](https://github.com/fonsp/Pluto.jl), and\n[Observable](https://observablehq.com/). IPyflow also enjoys cross-pollination\nof ideas with other reactive Python notebooks like\n[Marimo](https://github.com/marimo-team/marimo),\n[Jolin.io](https://cloud.jolin.io/), and\n[Datalore](https://blog.jetbrains.com/datalore/2021/10/11/revamped-reactive-mode-and-how-it-makes-your-notebooks-reproducible/)\n--- definitely check them out as well if you like IPyflow.\n\nWork on IPyflow has benefited from the support of folks from a number of\ncompanies -- both in the form of direct financial contributions\n([Databricks](https://www.databricks.com/), [Hex](https://hex.tech/)) as well\nas indirect moral support and encouragement ([Ponder](https://ponder.io/),\n[Meta](https://www.meta.com/)). And of course, IPyflow rests on the foundations\nbuilt by the incredible Jupyter community.\n\nLicense\n-------\nCode in this project licensed under the [BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause).\n","funding_links":[],"categories":["Python","Python程序"],"sub_categories":["资源传输下载"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fipyflow%2Fipyflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fipyflow%2Fipyflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fipyflow%2Fipyflow/lists"}