在IPython笔记本中读取单元格内容

33

我有一个混合了 markdownpythonipython 笔记本。

我希望我的一些 python 单元格能够读取相邻的 markdown 单元格,并将它们作为输入进行处理。

所需情况的示例:

单元格1(markdown):要执行的SQL代码

单元格2(markdown)select * from tbl where x=1

单元格3(python)mysql.query(ipython.previous_cell.content)

(语法 ipython.previous_cell.content 是虚构的)

执行“单元格3”应当等同于 mysql.query("select * from tbl where x=1")

如何实现这一点?


2
我会先问“这能做到吗?” 我认为这不是显而易见的。 - cel
1
无论如何,我们总是可以尝试解释.ipynb格式并读取单元格内容。 - Uri Goren
1
我可以问一下,你想通过这个实现什么目标吗? - Jorge Leitao
在同一个笔记本中编写sqlpigbash脚本,而不需要重复编写它们(对于可读的markdown单元格和执行它们的python单元格)。 - Uri Goren
是的,这可以做到,而且非常简单。笔记本只需要访问包含它的目录即可。您更喜欢从命令行运行它还是从笔记本GUI运行它? - alexis
对于非Python脚本,我会使用原始单元格而不是Markdown。这样可以避免注释变成标题、下划线变成斜体等问题。 - alexis
1个回答

29

我认为你正在错误的方向上尝试解决问题。

首先,是可能以一种非常hackish的方式获得相邻的Markdown单元格,但这种方式在无头笔记本执行中不起作用。

你想要做的是使用IPython单元格魔法,只要单元格以两个百分号和一个标识符开头,就允许任意语法。

通常你需要SQL单元格。

你可以参考有关单元格魔法的文档, 或者我可以向你展示如何构建它:

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

@magics_class
class StoreSQL(Magics):


    def __init__(self, shell=None,  **kwargs):
        super().__init__(shell=shell, **kwargs)
        self._store = []
        # inject our store in user availlable namespace under __mystore
        # name
        shell.user_ns['__mystore'] = self._store

    @cell_magic
    def sql(self, line, cell):
        """store the cell in the store"""
        self._store.append(cell)

    @line_magic
    def showsql(self, line):
        """show all recorded statements"""
        print(self._store)

    ## use ipython load_ext mechanisme here if distributed
    get_ipython().register_magics(StoreSQL)

现在您可以在Python单元格中使用SQL语法:

%%sql 
select * from foo Where QUX Bar

第二个单元格:

%%sql
Insert Cheezburger into Can_I_HAZ

检查我们执行的内容(三个连字符表示输入/输出分界线,您无需键入它们):

%showsql
---
['select * from foo Where QUX Bar', 'Insert Cheezburger into Can_I_HAZ']

你在问题开头提出的问题:

 mysql.query(__mystore[-1])

当然,这需要您按正确顺序执行之前的单元格,但并不妨碍您使用%%sql语法来为单元格命名,例如,如果_store是一个dict,或者更好地说是一个类,您可以重写__getattr__,以像__getitem__一样使用点语法访问字段。这留给读者作为练习,或在回复的末尾查看:

@cell_magic
def sql(self, line, cell):
    """store the cell in the store"""
    self._store[line.strip()] = cell

你可以像这样使用SQL单元格:

%%sql A1
set foo TO Bar where ID=9

然后在您的Python单元格中

mysql.execute(__mystore.A1)

我还强烈建议查看Catherine Develin SqlMagic,用于IPython,以及这个GitHub上的Notebook gist,展示了所有这些内容。

在您的评论中,您似乎想添加pig,没有任何阻碍您使用%%pig magic。也可以注入JavaScript以启用正确的SQL和PIG语法突出显示,但这超出了本问题的范围。


我对这个特定的解决方案没有需求,但这是关于IPython魔法的很棒的信息,谢谢! - alexis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接