2016-06-24 22 views
11

In un taccuino Jupyter sono presenti alcuni effetti magici incorporati che modificano il contenuto di una cella del notebook. Ad esempio, la magia %load sostituisce il contenuto della cella corrente con il contenuto di un file sul file system.Jupyter: Scrivi una magia personalizzata che modifica il contenuto della cella in cui si trova

Come posso scrivere un comando magico personalizzato che faccia qualcosa di simile?

Quello che ho stampe finora qualcosa da stdout

def tutorial_asset(line): 
    print('hello world') 


def load_ipython_extension(ipython): 
    ipython.register_magic_function(tutorial_asset, 'line') 

E posso caricarlo con %load_ext tutorial_asset. Ma da li sono perso.

[Edit]:

ho trovato un modo per ottenere l'istanza shell interattiva:

@magics_class 
    class MyMagics(Magics): 

     @line_magic 
     def tutorial_asset(self, parameters): 
      self.shell 

L'oggetto self.shell sembra dare l'accesso completo al set di cellule nel notebook, ma l'unico modo che posso trovare per modificare le celle è fare self.shell.set_next_input('print("hello world")'). Questo non è sufficiente perché, in un notebook Jupyter, quella cella di input viene saltata e non sovrascrive la cella di input, ma crea una nuova cella di input dopo di essa.

Questo andrebbe bene, ma se eseguo il notebook una seconda volta, crea un'altra cella di input con lo stesso file caricato, il che è fastidioso. Posso farlo caricare solo una volta, ad esempio, controllando se il contenuto è già nella cella successiva?

risposta

9

EDIT: Dopo aver scavato un po 'di più, ho scoperto che l'attuale build del notebook non può fare entrambe le cose.

Bene, questo è un po 'difficile ... Guardando il codice IPython, sembra che è necessario utilizzare set_next_input se si desidera sostituire la cella, e run_cell se si vuole realmente eseguire del codice. Tuttavia, non riesco a far funzionare entrambi contemporaneamente: sembra che set_next_input vinca sempre.

Scavando nel codice, il front-end Web supporta optional clearing of the output su set_next_input. Tuttavia, lo kernel doesn't yet support setting this flag (e quindi l'output verrà sempre cancellato come azione predefinita). Per fare meglio richiederà una patch per ipykernel.

Il miglior Ho quindi è il seguente codice, utilizzando jupyter notebook versione 4.2.1:

from __future__ import print_function 
from IPython.core.magic import Magics, magics_class, line_magic 

@magics_class 
class MyMagics(Magics): 

    @line_magic 
    def lmagic(self, line): 
     "Replace current line with new output" 
     raw_code = 'print("Hello world!")' 
     # Comment out this line if you actually want to run the code. 
     self.shell.set_next_input('# %lmagic\n{}'.format(raw_code), replace=True) 
     # Uncomment this line if you want to run the code instead. 
     # self.shell.run_cell(raw_code, store_history=False) 

ip = get_ipython() 
ip.register_magics(MyMagics) 

Questo vi dà un comando magica lmagic che o sostituire la cella corrente o eseguire il raw_code a seconda di quale un po 'del codice che hai commentato.

Problemi correlati