Нет доступа к переменным записной книжки в ipython cell_magic

Я пытаюсь выполнить некоторые манипуляции с файлом ROOT в ноутбуке ipython (ROOT здесь - программа анализа данных ROOT CERN с интерфейсом python). Одной из раздражающих особенностей ROOT является то, что он часто отправляет вывод непосредственно на стандартный вывод вместо того, чтобы возвращать такой вывод в виде строки. Чтобы этот вывод появился в результате в блокноте ipython, я написал немного cell_magic, что:

  • Сообщает ROOT перенаправить стандартный вывод в файл
  • Запускает команду python в ячейке
  • Отключает перенаправление вывода ROOT
  • Читает файл и печатает содержимое

Вот мой маленький клеточный волшебный код

import tempfile
import ROOT
from IPython.core.magic import register_cell_magic

@register_cell_magic
def rootprint(line, cell):
  """Capture Root stdout output and print in ipython notebook."""

  with tempfile.NamedTemporaryFile() as tmpFile:

    ROOT.gSystem.RedirectOutput(tmpFile.name, "w")
    exec cell
    ROOT.gROOT.ProcessLine("gSystem->RedirectOutput(0);")
    print tmpFile.read()

Если я помещу этот код в ячейку блокнота ipython и выполню его, то это отлично сработает. Например,

In [53]: f = ROOT.TFile('myRootFile.root')   # Load the Root file


In [54]: %%rootprint
         f.ls()  # Show the contents of the ROOT file

         ... f.ls() output appears here - yay! ...

Обычно вывод f.ls() отправляется на стандартный вывод и не отображается как результат ячейки. Но с этой магией ячейки вывод действительно появляется в результате ячейки! Это потрясающе!

НО, если я вставлю магический код ячейки в модуль, то он не сработает. Например, я помещаю этот код выше в ipythonRoot.py и делаю import ipythonRoot.py в блокноте. Когда я пытаюсь запустить ячейку %%rootprint выше, я получаю сообщение об ошибке, говорящее, что f не определено. Я попытался изменить строку exec на exec cell in globals(), но это не помогло.

Есть ли способ сделать это? Кроме того, есть ли лучший способ написать функцию cell_magic (например, должен ли я возвращать вывод вместо его печати)? Заранее благодарю за любую помощь!


person Adam    schedule 22.02.2013    source источник


Ответы (2)


Итак, я понял это, посмотрев код IPython, в частности, в IPython/core/magics/execution.py было несколько хороших подсказок. Вот мой новый модуль

import tempfile
import ROOT
from IPython.core.magic import (Magics, magics_class, cell_magic)

@magics_class
class RootMagics(Magics):
  """Magics related to Root.

      %%rootprint  - Capture Root stdout output and show in result cell
  """

    def __init__(self, shell):
      super(RootMagics, self).__init__(shell)

  @cell_magic
  def rootprint(self, line, cell):
    """Capture Root stdout output and print in ipython notebook."""

    with tempfile.NamedTemporaryFile() as tmpFile:

      ROOT.gSystem.RedirectOutput(tmpFile.name, "w")
      ns = {}
      exec cell in self.shell.user_ns, ns
      ROOT.gROOT.ProcessLine("gSystem->RedirectOutput(0);")
      print tmpFile.read()

# Register
ip = get_ipython() 
ip.register_magics(RootMagics)

Обратите внимание на использование класса Magics и атрибута shell, который содержит, среди прочего, пространство имен записной книжки. Его можно регулярно импортировать, и он отлично работает.

person Adam    schedule 23.02.2013
comment
Обратите внимание, что есть ярлык — если вы используете экземпляр IPython (переданный __init__ как shell), вы можете вызвать shell.ex(cell) для выполнения кода. - person Thomas K; 23.02.2013

Если я правильно понимаю, пространство имен magic/alias/user отдельно. выполнение «импорта» не будет мешать пространству имен magic/alias. по этой причине существует магия %load_ext, но вы должны определить свою точку входа. [Пример с R magic].(https://github.com/ipython/ipython/blob/master/IPython/extensions/rmagic.py#L617).

Также я бы посоветовал посмотреть как захват магии который фиксирует stdout/err без временных файлов.

Как только это сработает, вы также можете добавить свое расширение в указатель расширений.

person Matt    schedule 23.02.2013
comment
Спасибо за хорошие подсказки! Одна проблема с Root заключается в том, что он самостоятельно обрабатывает stdout/err, поэтому я не думаю, что есть способ указать ему перенаправить в файл. - person Adam; 23.02.2013