2016-06-24 6 views
11
.

В ноутбуке Jupyter есть встроенная магия, которая изменяет содержимое ячейки ноутбука. Например, маска %load заменяет содержимое текущей ячейки содержимым файла в файловой системе.Jupyter: напишите настраиваемое волшебство, которое изменяет содержимое ячейки в

Как написать специальную магическую команду, которая делает что-то подобное?

То, что я до сих пор печатает что-то стандартный вывод

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


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

И я могу загрузить его с %load_ext tutorial_asset. Но оттуда я потерялся.

[Изменить]:

Я нашел способ добраться до интерактивного экземпляра оболочки:

@magics_class 
    class MyMagics(Magics): 

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

Объект self.shell, кажется, дает полный доступ к множеству ячеек в записной книжке, но единственный способ изменить ячейки - сделать self.shell.set_next_input('print("hello world")'). Этого недостаточно, потому что в ноутбуке Jupyter эта входная ячейка пропускается, и она не перезаписывает входную ячейку, а вместо нее создает новую ячейку ввода после нее.

Это было бы хорошо, но если я запустил ноутбук второй раз, он создаст другую ячейку ввода с тем же загруженным файлом, что раздражает. Могу ли я загрузить его только один раз, скажем, путем проверки того, находится ли содержимое в следующей ячейке?

ответ

9

EDIT: После небольшого дальнейшего копания, я обнаружил, что текущая сборка ноутбука не может обойти оба.

Ну, это немного сложнее ... Глядя на код IPython, похоже, вам нужно использовать set_next_input, если вы хотите заменить ячейку и run_cell, если вы действительно хотите запустить код. Тем не менее, я не могу заставить обоих работать сразу - похоже, set_next_input всегда выигрывает.

Копаем в код, передние опорные стойки optional clearing of the output на set_next_input. Однако, kernel doesn't yet support setting this flag (и поэтому вывод всегда будет очищен как действие по умолчанию). Чтобы сделать лучше, потребуется патч для ipykernel.

Лучший поэтому у меня есть следующий код, используя jupyter ноутбук версии 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) 

Это дает вам волшебную команду lmagic, которые будут либо заменить текущую ячейку или запустить raw_code в зависимости от бит кода, который вы закомментировали.