如何在IPython(笔记本)shell命令中提供内联输入?

5

我想制作一个IPython笔记本,其中包含一些shell命令及其输入。在bash提示符中,我可以使用“here-document”语法:

bash-3.2$ mysql -u root <<END_IPUT
> use mydb;
> show tables;
> END_INPUT

我该如何在IPython中实现相同的效果,特别是在jupyter笔记本中?我知道如何将shell命令作为“行魔法”或“单元格魔法”在IPython中执行,例如:

In [7]:  !! ls -tF
Out[7]:  ['Demo-notebook.ipynb',
          'createdb.sql',
          ...

我查看了IPython作为系统shell的文档,它展示了如何启用一些语法美化。在下面的代码中,我可以直接运行系统命令而不需要在前面加上!!!

# Turn everything in $PATH into an alias; 
# then enable calling aliases without ! or %
%rehashx      
%autocall 2 

但是这些方法都无法在命令中提供输入:here-document语法在IPython中无效,会导致Python SyntaxError。那么我该怎么做呢?


你尝试过使用bash cell magic吗?在单元格中以%%bash开头,并在其余部分放置bash代码。 - Thomas K
1
好的建议,谢谢!我已经找到了%%sx,我认为它做的和你说的一样。但是%bash的文档让我找到了%%script,这正是我要找的。同时,我还发现了一个专门针对sql的扩展,更好地解决了我的问题。但如果你想写一个扩展你建议的答案,我会接受它。 - alexis
@Thomas,在你第三次删除我的标签之前,看看每个标签有多少人关注。如果 [tag:ipython-notebook] 是个问题,请着手合并这些标签的过程。 - alexis
我正在尝试合并标签,但在新标签的使用量达到旧标签的80%之前,我无法这样做。我会定期将新问题转移到新标签以提高其数量。谢谢。 - Thomas K
我明白了。好的,请不要删除我的标签。对你来说,拥有两个标签应该足够了。(并且只需将 [tag:jupyter-notebook] 添加到其他问题中即可。)当然,也可以将这些标签本身设为同义词。 - alexis
我将jupyter-notebook设置为ipython-notebook的同义词,但你需要反过来设置(因为我在新标签中没有足够的权限)。 - alexis
2个回答

8

bash单元格魔法允许您输入多行bash代码。只需在任何单元格前面加上%%bash

%%bash
echo "This is bash"
ls

如果您正在使用heredoc将文本导入另一个程序,则还可以使用脚本单元格魔术操作:

%%script bc
2+3

还可能有其他单元格魔法可以更具体地解决您的问题!


1
在运行命令时,!%%bash 之间有一些小差别。1. 使用 %%bash 时不会显示 ASCII 颜色,而使用 ! 时颜色会正常显示。2. %%bash 会收集输出并一次性刷新到屏幕上,而 ! 则会在执行过程中逐个显示输出。 - Mahmoud

6

通过进一步的研究,并借助于@ThomasK的提示(查看被接受的答案),我找到了几种实现此操作的方法。

  • One solution is the cell magic %sx. It executes the cell contents as a bash script, and captures and returns the output as a list of lines. Sometimes handy, sometimes not.

    In[1]:  %%sx
            echo Hello, world
            cat -n <<DATA
            this
            and that
            DATA
    
    Out[1]: ['Hello, world', '     1\tthis', '     2\tand that']
    
  • Change that to %%bash, as @ThomasK suggested, and the output is printed out, not returned. To capture it for further processing, ipython provides the --out parameter. But then I need to print it myself-- it won't show up by default.

    In[1]:  %%bash --out var
            echo Hello, world
            echo "   Again"
    
    In[2]:  var
    
    Out[2]: 'Hello, world\n   Again\n'
    
  • %%bash is actually shorthand for %%script bash, billed as working "like the #! line in a script" (see the help with %%script?). Which it does. So here's how to dispense with the here-document syntax and have any program read the cell contents as input. %%script also accepts the --out parameter.

            %%script --out var mysql -u root -p XYZ
            USE somedb;
            SELECT * FROM users
                 WHERE passwd IS NULL\G
    

这个工具虽然不错,但我最终没有使用它,因为我的用例是mysql,后来我发现有一个很棒的第三方ipython-sql扩展可以代替它:

%load_ext sql
%sql mysql+pymysql://user:passwd@localhost/somedb

这需要先安装扩展程序,使用pip install ipython-sql命令进行安装。对于mysql,还需执行pip install pymysql命令。完成上述设置后,可以像这样与数据库交互:

In[1]:  %%sql 
        SELECT * FROM users
            WHERE passwd IS NULL

Out[1]: 1 rows affected.
        ...

返回的表格实际上是一张带有边框的笔记本表格,这很有用。它作为Pandas dataframe(一种智能列表)提供,并可以从_中获取。


我可以这样做:%% bash /usr/bin/env ipython,以便在命令行中运行一个导出的 notebook.py 吗? - jtlz2

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