6
6
# contextlib, and we `await yield_()` instead of just `yield`
7
7
from async_generator import asynccontextmanager , async_generator , yield_
8
8
9
- import nest_asyncio
10
-
11
9
from time import monotonic
12
10
from queue import Empty
13
11
import asyncio
18
16
from nbformat .v4 import output_from_msg
19
17
20
18
from .exceptions import CellTimeoutError , DeadKernelError , CellExecutionComplete , CellExecutionError
19
+ from .util import run_sync
21
20
22
21
23
22
def timestamp ():
@@ -97,6 +96,21 @@ class NotebookClient(LoggingConfigurable):
97
96
),
98
97
).tag (config = True )
99
98
99
+ nest_asyncio = Bool (
100
+ False ,
101
+ help = dedent (
102
+ """
103
+ If False (default), then blocking functions such as `execute`
104
+ assume that no event loop is already running. These functions
105
+ run their async counterparts (e.g. `async_execute`) in an event
106
+ loop with `asyncio.run_until_complete`, which will fail if an
107
+ event loop is already running. This can be the case if nbclient
108
+ is used e.g. in a Jupyter Notebook. In that case, `nest_asyncio`
109
+ should be set to True.
110
+ """
111
+ ),
112
+ ).tag (config = True )
113
+
100
114
force_raise_errors = Bool (
101
115
False ,
102
116
help = dedent (
@@ -367,21 +381,9 @@ async def setup_kernel(self, **kwargs):
367
381
self .kc .stop_channels ()
368
382
self .kc = None
369
383
370
- def execute (self , ** kwargs ):
371
- """
372
- Executes each code cell (blocking).
373
-
374
- Returns
375
- -------
376
- nb : NotebookNode
377
- The executed notebook.
378
- """
379
- loop = get_loop ()
380
- return loop .run_until_complete (self .async_execute (** kwargs ))
381
-
382
384
async def async_execute (self , ** kwargs ):
383
385
"""
384
- Executes each code cell asynchronously .
386
+ Executes each code cell.
385
387
386
388
Returns
387
389
-------
@@ -404,6 +406,8 @@ async def async_execute(self, **kwargs):
404
406
405
407
return self .nb
406
408
409
+ execute = run_sync (async_execute )
410
+
407
411
def set_widgets_metadata (self ):
408
412
if self .widget_state :
409
413
self .nb .metadata .widgets = {
@@ -550,48 +554,9 @@ def _check_raise_for_error(self, cell, exec_reply):
550
554
if (exec_reply is not None ) and exec_reply ['content' ]['status' ] == 'error' :
551
555
raise CellExecutionError .from_cell_and_msg (cell , exec_reply ['content' ])
552
556
553
- def execute_cell (self , cell , cell_index , execution_count = None , store_history = True ):
554
- """
555
- Executes a single code cell (blocking).
556
-
557
- To execute all cells see :meth:`execute`.
558
-
559
- Parameters
560
- ----------
561
- cell : nbformat.NotebookNode
562
- The cell which is currently being processed.
563
- cell_index : int
564
- The position of the cell within the notebook object.
565
- execution_count : int
566
- The execution count to be assigned to the cell (default: Use kernel response)
567
- store_history : bool
568
- Determines if history should be stored in the kernel (default: False).
569
- Specific to ipython kernels, which can store command histories.
570
-
571
- Returns
572
- -------
573
- output : dict
574
- The execution output payload (or None for no output).
575
-
576
- Raises
577
- ------
578
- CellExecutionError
579
- If execution failed and should raise an exception, this will be raised
580
- with defaults about the failure.
581
-
582
- Returns
583
- -------
584
- cell : NotebookNode
585
- The cell which was just processed.
586
- """
587
- loop = get_loop ()
588
- return loop .run_until_complete (
589
- self .async_execute_cell (cell , cell_index , execution_count , store_history )
590
- )
591
-
592
557
async def async_execute_cell (self , cell , cell_index , execution_count = None , store_history = True ):
593
558
"""
594
- Executes a single code cell asynchronously .
559
+ Executes a single code cell.
595
560
596
561
To execute all cells see :meth:`execute`.
597
562
@@ -654,6 +619,8 @@ async def async_execute_cell(self, cell, cell_index, execution_count=None, store
654
619
self .nb ['cells' ][cell_index ] = cell
655
620
return cell
656
621
622
+ execute_cell = run_sync (async_execute_cell )
623
+
657
624
def process_message (self , msg , cell , cell_index ):
658
625
"""
659
626
Processes a kernel message, updates cell state, and returns the
@@ -809,15 +776,3 @@ def execute(nb, cwd=None, km=None, **kwargs):
809
776
if cwd is not None :
810
777
resources ['metadata' ] = {'path' : cwd }
811
778
return NotebookClient (nb = nb , resources = resources , km = km , ** kwargs ).execute ()
812
-
813
-
814
- def get_loop ():
815
- try :
816
- loop = asyncio .get_event_loop ()
817
- except RuntimeError :
818
- loop = asyncio .new_event_loop ()
819
- asyncio .set_event_loop (loop )
820
- return loop
821
-
822
-
823
- nest_asyncio .apply ()
0 commit comments