如何将ipython魔术输出存储到变量中

时间:2015-05-05 17:07:50

标签: python ipython ipython-magic

我是一个python和Ipython初学者。这可能是一个微不足道的问题。它可能与其他问题重复。但是我不知道应该搜索哪些关键词。

我已经知道如何与shell交互。

例如:

In [1]: a = !ls
In [2]: a
        ...same ls result as shell...
In [3]: type(a)
Out[3]: IPython.utils.text.SList

但是,如何与Ipython魔术互动?

例如

In [1]: a = %history -t 
        ...Ipython result...
In [2]: a
In [3]: type(a)
Out[3]: NoneType

5 个答案:

答案 0 :(得分:2)

对于history命令,具体来说,最简单的解决方案是

In [243]: history -t -f history.txt
In [244]: with open('history.txt') as f:
   .....:     HIST = [l.strip() for l in f]
   .....:     

In [245]: len(HIST)
Out[245]: 258

In [246]: HIST[-1]
Out[246]: "get_ipython().magic(u'history -t -f history.txt')"

In [247]: 

基本上,将其转储到文件中并将其读回。

这可能看起来像是一块垃圾,但我怀疑它来自IPython的本质。它实际上不是解释器,而是底层解释器的命令行shell。我怀疑魔术命令是在IPython中处理的,并且没有通过将命令传递给解释器,捕获输出并将其作为Out [n]存储在命令历史中的正常路径。因此无法召回和分配。

另一种方法是get_ipython().magic只返回None

无论哪种方式,%history的屏幕输出d =都不可用。您必须将其转储到文件中。

似乎每个魔法命令都有所不同。例如,alias会返回屏幕输出

In [288]: a=%alias
Total number of aliases: 17

In [289]: a
Out[289]: 
[('cat', 'cat'),
 ('clear', 'clear'),
 ('cp', 'cp'),
 ('ldir', 'ls -F -G -l %l | grep /$'),
 ('less', 'less'),
 ('lf', 'ls -F -l -G %l | grep ^-'),
 ('lk', 'ls -F -l -G %l | grep ^l'),
 ('ll', 'ls -F -l -G'),
 ('ls', 'ls -F -G'),
 ('lx', 'ls -F -l -G %l | grep ^-..x'),
 ('man', 'man'),
 ('mkdir', 'mkdir'),
 ('more', 'more'),
 ('mv', 'mv'),
 ('rm', 'rm'),
 ('rmdir', 'rmdir'),
 (u'show', u'echo')]

In [290]: 

答案 1 :(得分:1)

至少对于%history命令,输出被写入到stdout,因此通过将其重定向到StringIO,您可以捕获输出而无需任何临时文件,如下所示:

@register_line_magic
def get_magic_out(command):
    ipy = get_ipython()
    out = io.StringIO()

    with redirect_stdout(out):
        ipy.magic(command)

    return out.getvalue()

Gist: get_magic_out.py

然后您可以像这样使用:

In [1]: import get_magic_out as _ # We don't actually use the module, because of the `@register_line_magic` decorator

In [2]: x = %get_magic_out history

In [3]: x
Out[3]: 'import get_magic_out\nx = %get_magic_out history\n'

答案 2 :(得分:0)

我正在开发一个ipython重装项目,希望能够快速选择以前的%run语句。我的解决方案如下。

import os

histvar = os.popen("ipython -c 'history -g'").read()

#regex match / do stuff here

答案 3 :(得分:0)

使用线魔术,您可以使用result = %lsmagic将结果转换为变量; 借助单元魔术,多亏了ipython,您可以使用_来获得结果,例如:

%%some_magics
balabala
balabala

a = _

答案 4 :(得分:0)

我知道这是一个非常老的问题,但是此功能的文档记录很少,所以我认为我至少要尝试在此处记录如何做到这一点,并避免其他人遇到同样的麻烦。 TLDR:使用@needs_local_scope并用您的值更新local_ns字典。

对于更详细的解决方案,我想返回动态变量,每个变量都是一个熊猫数据框。最后,这就是我正在工作的Juypter笔记本的外观:

In  [1]: %load_ext faker_maker

In  [2]: %%build_fake_dataframes
         names
         ----
         first_name
         last_name

In  [3]: names
Out [3]:
            first_name    last_name
         0        Fred        Smith
         1      George         Wood

要使以上内容正常工作,我还有一个名为faker_maker.py的文件,其内容如下:

from IPython.core.magic import (Magics, magics_class, register_cell_magic,
                                line_cell_magic, needs_local_scope)
import pandas as pd

class FakeDataFrameBuilder():
    dataframes = {}

    def __init__(text):
        ...

    def parse():
        ...

@magics_class
class AutoMagics(Magics):
    @needs_local_scope
    @line_cell_magic
    def build_fake_dataframes(self, line, cell, local_ns=None):
        cls = FakeDataFrameBuilder(cell)
        cls.parse()
        for name, df in cls.dataframes.items():
            local_ns[name] = df

def load_ipython_extension(ipython):
    ipython.register_magics(AutoMagics)

我也有一个重要提示:

  • 每次更改*.py文件时,请确保在Jupyter中重新启动内核。这是必需的,以便%load_ext可以重新加载文件。