# How to update handler of server extension without restarting Jupyter?

**URL:** <https://discourse.jupyter.org/t/how-to-update-handler-of-server-extension-without-restarting-jupyter/20401>\
**Category:** extensions\
**Tags:** how-to, help-wanted\
**Created:** [July 14, 2023, 1:24am UTC](https://discourse.jupyter.org/t/how-to-update-handler-of-server-extension-without-restarting-jupyter/20401 "2023-07-14T01:24:36Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![alexheat](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.jupyter.org/alexheat/32/10410_2.png) [@alexheat](https://discourse.jupyter.org/u/alexheat)\
**Post date:** [July 14, 2023, 1:24am UTC](https://discourse.jupyter.org/t/how-to-update-handler-of-server-extension-without-restarting-jupyter/20401/1 "2023-07-14T01:24:36Z")

</div>

Hello I am following the example of how to create a server-side extension here [https://github.com/jupyterlab/extension-examples/tree/main/server-extension](https://github.com/jupyterlab/extension-examples/tree/main/server-extension)

When I make changes to the handler.py file, the the changes are not available in Jupyter until I stop Jupyter completely and then re run it. Is there way to update that module without totally restarting Jupyter?

This is basically the same question that was asked here [Jupyterlab 2 --watch does not update on server extension python changes](https://discourse.jupyter.org/t/jupyterlab-2-watch-does-not-update-on-server-extension-python-changes/9068) but it was not answered.

---

<div class="post-metadata">

**Author:** ![alexheat](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.jupyter.org/alexheat/32/10410_2.png) [@alexheat](https://discourse.jupyter.org/u/alexheat)\
**Post date:** [July 14, 2023, 1:25am UTC](https://discourse.jupyter.org/t/how-to-update-handler-of-server-extension-without-restarting-jupyter/20401/2 "2023-07-14T01:25:44Z")

</div>

@fcollonval since you are creator of this fine example. Thank you!

---

<div class="post-metadata">

**Author:** ![bollwyvl](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.jupyter.org/bollwyvl/32/904_2.png) [@bollwyvl](https://discourse.jupyter.org/u/bollwyvl)\
**Post date:** [July 14, 2023, 1:42pm UTC](https://discourse.jupyter.org/t/how-to-update-handler-of-server-extension-without-restarting-jupyter/20401/3 "2023-07-14T13:42:02Z")

</div>

An approach is to run two servers:

- start one, as usual, from the command line on e.g. `8888`
- start a second one on `8889` with the Python API from _inside a running IPython kernel_ on the same event loop as the kernel

```python
from jupyter_server.serverapp import ServerApp

app = ServerApp()
app.initialize(["--port=8889"])
app.start_app()
print(app.display_url.splitlines()[0])

```

In that mess, one should see the new `token`, so a second browser tab can be opened to the `display_url` that gets printed.

This also _generally_ works with IPython’s `%autoreload 2`, such that one can work on at-rest `.py` files, but there are limits… sometimes it can be effective to do prototyping in a notebook, then move the code to `.py` when they are ready to be tested.

While in this prototyping phase, one has access to the second running server, and can change _just about_ anything about what it knows. For example, one can make a handler…

```python
from jupyter_server.base.handlers import APIHandler
from tornado.web import authenticated

class SumHandler(APIHandler):
    @authenticated
    async def get(self, a, b):
        self.finish({"sum": float(a) + float(b)})

app.web_app.add_handlers(".*", [
    (app.base_url + r"sum/(-?[0-9.]+)/(-?[0-9.]+)", SumHandler),
])

```

… and make a request against it from within the same kernel:

```python
from tornado.escape import json_decode
from tornado.httpclient import AsyncHTTPClient

client = AsyncHTTPClient()
r = await client.fetch(f"http://127.0.0.1:8890/sum/1/2?token={app.token}")
print(json_decode(r.body))

```

Note that something like `requests` would block, so the whole thing would grind to a halt: one can use a _second_ kernel to make such requests, but then the token has to be known between servers.
