Asserts fail with no message
I was trying to programmatically interact with the nbclient package and kept getting blank assertion errors being thrown. It was a bit of a mess on my end to track down since nbclient was being hidden behind numerous other libraries I was working with, here's one of the ones which would regularly throw, indicating that there is no kernel available:
https://github.com/jupyter/nbclient/blob/2650b217c4c9965110ceb4de193092d7eb36c2bb/nbclient/client.py#L960
Any reason to use asserts here instead of something more friendly to calling libraries, e.g. a new KernelNotConfiguredException?
It seems that this was used for static type checking, meaning that it should never happen at runtime either. Could you share how you use nbclient?
Yes, I'm building a wrapper for nbclient to make available some of the notebook functions to an LLM agent. More specifically, I'm making a few high level functions like execute_cell() available as tools to langchain agents so that one can ask an LLM with tool support to do things like load, change, execute, and evaluate notebooks.
Here's a bit of pseudocode showing what the workflow looks like:
notebook = nbformat.reads(notebook_content, as_version=4)
client = NotebookClient(notebook)
index=0
for cell in notebook.cells:
if cell.id == id:
result = client.execute_cell(cell, index)
else:
index += 1
That code likely won't run nicely fwiw, it's sort of ripped out of the stuff I'm building now, and it's possible that code does actually run and initialization of a NotebookClient without a kernel or kernel manager isn't an issue normally and my langchain code is getting in the way.
Here is a better MWE:
from nbclient import NotebookClient
import nbformat
notebook = nbformat.reads(open('test.ipynb','r').read(), as_version=4)
client = NotebookClient(notebook, kernel_name="python3")
for index, cell in enumerate(notebook.cells):
result = client.execute_cell(cell, index)
Which gives unexpected error:
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
Cell In[14], [line 8](vscode-notebook-cell:?execution_count=14&line=8)
[5](vscode-notebook-cell:?execution_count=14&line=5) client = NotebookClient(notebook, kernel_name="python3")
[7](vscode-notebook-cell:?execution_count=14&line=7) for index, cell in enumerate(notebook.cells):
----> [8](vscode-notebook-cell:?execution_count=14&line=8) result = client.execute_cell(cell, index)
File ~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/jupyter_core/utils/__init__.py:159, in run_sync.<locals>.wrapped(*args, **kwargs)
[157](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/jupyter_core/utils/__init__.py:157) if name not in _runner_map:
[158](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/jupyter_core/utils/__init__.py:158) _runner_map[name] = _TaskRunner()
--> [159](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/jupyter_core/utils/__init__.py:159) return _runner_map[name].run(inner)
[160](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/jupyter_core/utils/__init__.py:160) except RuntimeError:
[161](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/jupyter_core/utils/__init__.py:161) pass
File ~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/jupyter_core/utils/__init__.py:126, in _TaskRunner.run(self, coro)
[124](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/jupyter_core/utils/__init__.py:124) self.__runner_thread.start()
[125](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/jupyter_core/utils/__init__.py:125) fut = asyncio.run_coroutine_threadsafe(coro, self.__io_loop)
--> [126](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/jupyter_core/utils/__init__.py:126) return fut.result(None)
File /usr/lib/python3.12/concurrent/futures/_base.py:456, in Future.result(self, timeout)
[454](https://file+.vscode-resource.vscode-cdn.net/usr/lib/python3.12/concurrent/futures/_base.py:454) raise CancelledError()
[455](https://file+.vscode-resource.vscode-cdn.net/usr/lib/python3.12/concurrent/futures/_base.py:455) elif self._state == FINISHED:
--> [456](https://file+.vscode-resource.vscode-cdn.net/usr/lib/python3.12/concurrent/futures/_base.py:456) return self.__get_result()
[457](https://file+.vscode-resource.vscode-cdn.net/usr/lib/python3.12/concurrent/futures/_base.py:457) else:
[458](https://file+.vscode-resource.vscode-cdn.net/usr/lib/python3.12/concurrent/futures/_base.py:458) raise TimeoutError()
File /usr/lib/python3.12/concurrent/futures/_base.py:401, in Future.__get_result(self)
[399](https://file+.vscode-resource.vscode-cdn.net/usr/lib/python3.12/concurrent/futures/_base.py:399) if self._exception:
[400](https://file+.vscode-resource.vscode-cdn.net/usr/lib/python3.12/concurrent/futures/_base.py:400) try:
--> [401](https://file+.vscode-resource.vscode-cdn.net/usr/lib/python3.12/concurrent/futures/_base.py:401) raise self._exception
[402](https://file+.vscode-resource.vscode-cdn.net/usr/lib/python3.12/concurrent/futures/_base.py:402) finally:
[403](https://file+.vscode-resource.vscode-cdn.net/usr/lib/python3.12/concurrent/futures/_base.py:403) # Break a reference cycle with the exception in self._exception
[404](https://file+.vscode-resource.vscode-cdn.net/usr/lib/python3.12/concurrent/futures/_base.py:404) self = None
File ~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:960, in NotebookClient.async_execute_cell(self, cell, cell_index, execution_count, store_history)
[920](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:920) async def async_execute_cell(
[921](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:921) self,
[922](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:922) cell: NotebookNode,
(...)
[925](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:925) store_history: bool = True,
[926](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:926) ) -> NotebookNode:
[927](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:927) """
[928](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:928) Executes a single code cell.
[929](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:929)
(...)
[958](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:958) The cell which was just processed.
[959](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:959) """
--> [960](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:960) assert self.kc is not None
[962](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:962) await run_hook(self.on_cell_start, cell=cell, cell_index=cell_index)
[964](https://file+.vscode-resource.vscode-cdn.net/home/brooksch/sandboxes/jupyter_tool/~/sandboxes/jupyter_tool/.venv/lib/python3.12/site-packages/nbclient/client.py:964) if cell.cell_type != "code" or not cell.source.strip():
AssertionError:
Odd to me is that I can actually execute the whole notebook it appears, so maybe I am misusing the cell execution api? This code seems to work (and at the least does not throw the assertion error):
from nbclient import NotebookClient
import nbformat
notebook = nbformat.reads(open('test.ipynb','r').read(), as_version=4)
client = NotebookClient(notebook, kernel_name="python3")
client.execute()
Just an update for those who might be running into a similar problem or are trying to use the nbclient package in a similar way, this is how I create and init a new NotebookClient such that I can execute individual cells.
from nbclient import NotebookClient
import nbformat
notebook = nbformat.reads(open('test.ipynb','r').read(), as_version=4)
client = NotebookClient(notebook, kernel_name="python3")
client.km = client.create_kernel_manager()
client.start_new_kernel()
client.kc=client.start_new_kernel_client()
for index, cell in enumerate(notebook.cells):
print(f"Executing cell {index}")
result = client.execute_cell(cell, index)