diff --git a/jupyter_server/services/nbconvert/handlers.py b/jupyter_server/services/nbconvert/handlers.py index 97886f1878..ae4aab8e18 100644 --- a/jupyter_server/services/nbconvert/handlers.py +++ b/jupyter_server/services/nbconvert/handlers.py @@ -1,5 +1,11 @@ import json +try: + from anyio.to_thread import run_sync +except ImportError: + # fallback on anyio v2 for python version < 3.7 + from anyio import run_sync_in_worker_thread as run_sync + from tornado import web from ...base.handlers import APIHandler @@ -8,16 +14,18 @@ class NbconvertRootHandler(APIHandler): @web.authenticated - def get(self): + async def get(self): try: from nbconvert.exporters import base except ImportError as e: raise web.HTTPError(500, "Could not import nbconvert: %s" % e) from e res = {} - exporters = base.get_export_names() + # Some exporters use the filesystem when instantiating, delegate that + # to a thread so we don't block the event loop for it. + exporters = await run_sync(base.get_export_names) for exporter_name in exporters: try: - exporter_class = base.get_exporter(exporter_name) + exporter_class = await run_sync(base.get_exporter, exporter_name) except ValueError: # I think the only way this will happen is if the entrypoint # is uninstalled while this method is running