【问题标题】:How to hide code from cells in ipython notebook visualized with nbviewer?如何在使用 nbviewer 可视化的 ipython 笔记本中隐藏单元格中的代码?
【发布时间】:2015-03-12 03:52:01
【问题描述】:

我有一个使用 NBviewer 可视化的 ipython/jupyter 笔记本。

如何隐藏 NBviewer 呈现的笔记本中的所有代码,以便只显示代码的输出(例如绘图和表格)和降价单元格?

【问题讨论】:

  • 默认 UI(2016 年 2 月)中仍然没有用于此功能的现有按钮。恕我直言,这真的很烦人。这在将要实现的功能列表中:github.com/jupyter/notebook/issues/534 太好了。我很期待。
  • 请看下面诺亚的回答。通过包含 TemplateExporter,这个问题可以独立于输出格式来解决。在撰写本文时,Noahs 的答案取代了harsils 的答案(对于 TemplateExporter,这是一个很好的解决方案)。

标签: javascript ipython ipython-notebook


【解决方案1】:
from IPython.display import HTML

HTML('''<script>
code_show=true; 
function code_toggle() {
 if (code_show){
 $('div.input').hide();
 } else {
 $('div.input').show();
 }
 code_show = !code_show
} 
$( document ).ready(code_toggle);
</script>
<form action="javascript:code_toggle()"><input type="submit" value="Click here to toggle on/off the raw code."></form>''')

【讨论】:

  • 如果我将 iPython 3.1.0 放在代码单元格中,则为我工作。我用简单的 HTML 替换了 &lt;form action ... &gt; ... &lt;/form&gt;,例如 The raw code for this IPython notebook is by default hidden for easier reading.To toggle on/off the raw code, click &lt;a href="javascript:code_toggle()"&gt;here&lt;/a&gt;.
  • 感谢您的回答!如果您需要隐藏按钮以及隐藏或显示某些代码块(如 Rstudio)的能力,请参阅我的答案。
  • 谢谢,这也适用于“保存到 html”。建议将其放在笔记本顶部的自己的单元格中。
  • 你将如何改变它,使它甚至不显示按钮,它只是隐藏代码?
  • 它是否仅适用于特定版本的 Ipython?它曾经为我工作,但后来我更新了一些包(包括 Ipython),这不再工作了。
【解决方案2】:

现在可以直接从 nbconvert 版本 5.2.1 开始执行此操作:可以使用内置的 template exporter exclude options 过滤内容。例如:

jupyter nbconvert --to pdf --TemplateExporter.exclude_input=True my_notebook.ipynb

将排除“输入代码”单元格,即代码本身。 Similar options 用于排除提示、降价单元格或输出,或同时排除输入和输出。

(无论输出格式如何,这些选项都应该有效。)

【讨论】:

  • 这是最好的答案
  • .pdf导出默认保存在哪里?
  • 与 .ipython 笔记本相同的文件夹。使用参数 '--output NotebookNoCode' 重命名文件。
  • 这应该在笔记本中运行吗?
  • @were_cat 不,这是一个用于导出 .ipynb 笔记本文件的 shell 命令;在这个例子中,它被转换为 pdf
【解决方案3】:

我会使用 nbextensions (https://github.com/ipython-contrib/IPython-notebook-extensions) 中的 hide_input_all。方法如下:

  1. 找出你的 IPython 目录在哪里:

    from IPython.utils.path import get_ipython_dir
    print get_ipython_dir()
    
  2. 下载 nbextensions 并将其移至 IPython 目录。

  3. 在 IPython 目录(我的 在 profile_default/static/custom) 中类似于 custom.example.jsnbextensions 目录中。

  4. 将此行添加到 custom.js

    IPython.load_extensions('usability/hide_input_all')
    

IPython Notebook 现在将有一个按钮来切换代码单元格,无论工作簿是什么。

【讨论】:

  • 刚试过这个 - 它似乎有助于在编辑笔记本时隐藏代码单元,尽管当将笔记本保存为 html(即渲染到 nbviewer)时,代码单元仍然会出现。
  • @VivekGani 只是一个简短的说明,您可以使用相同 repo 提供的模板将隐藏的单元格隐藏在导出的 html 中,请参阅relevant doc page(另请参阅this relevant question)跨度>
【解决方案4】:

我编写了一些代码来实现这一点,并添加了一个按钮来切换代码的​​可见性。

笔记本顶部的代码单元格中包含以下内容:

from IPython.display import display
from IPython.display import HTML
import IPython.core.display as di # Example: di.display_html('<h3>%s:</h3>' % str, raw=True)

# This line will hide code by default when the notebook is exported as HTML
di.display_html('<script>jQuery(function() {if (jQuery("body.notebook_app").length == 0) { jQuery(".input_area").toggle(); jQuery(".prompt").toggle();}});</script>', raw=True)

# This line will add a button to toggle visibility of code blocks, for use with the HTML export version
di.display_html('''<button onclick="jQuery('.input_area').toggle(); jQuery('.prompt').toggle();">Toggle code</button>''', raw=True)

你可以看到an example of how this looks in NBviewer here

更新:这将在 Jupyter 中对 Markdown 单元格产生一些有趣的行为,但在笔记本的 HTML 导出版本中可以正常工作。

【讨论】:

  • 这适用于代码单元格,但如果你有降价单元格,它会做一些奇怪的事情。它显示 markdown as markdown,然后在下面显示相同的内容——但已格式化。
  • 我刚刚发现唯一错误的是节点规范。而不是'.input_area''.prompt',使用'div.input',它就像一个魅力!回顾一下,用jQuery("div.input").toggle(); 代替jQuery('.input_area').toggle(); jQuery('.prompt').toggle();。 @Max Masnick,你能解决你的答案吗?
  • 只要您不与降价单元格交互,使用“div.input”作为节点选择就可以工作,但我只是想通如果您确实与降价单元格进行交互,您可能会得到一些时髦的行为。例如,如果您双击一个降价单元格,则它会完全隐藏。因此,我对 Max 解决方案的调整适用于生成 HTML 以与他人共享,但不适用于随后与其进行太多交互。
  • 是的,所以我注意到你对 Markdown 单元所做的同样的事情。它在我使用它的 HTML 导出中运行良好。我将编辑答案以说明这一点。
  • 要从删除“.prompt”中删除剩余的右边空格,只需将此代码添加到上述代码的末尾即可。 CSS = """#notebook div.output_subarea { max-width:100%;"""HTML('&lt;style&gt;{}&lt;/style&gt;'.format(CSS))。这对于打印非常有用。
【解决方案5】:

最新的 IPython 笔记本版本不再允许在 markdown 单元格中执行 javascript,因此使用以下 javascript 代码添加新的 markdown 单元格将无法隐藏您的代码单元格(请参阅this link

修改 ~/.ipython/profile_default/static/custom/custom.js 如下:

code_show=true;
function code_toggle() {
 if (code_show){
 $('div.input').hide();
 } else {
 $('div.input').show();
 }
 code_show = !code_show
}

$([IPython.events]).on("app_initialized.NotebookApp", function () {
  $("#view_menu").append("<li id=\"toggle_toolbar\" title=\"Show/Hide code cells\"><a href=\"javascript:code_toggle()\">Toggle Code Cells</a></li>")
});

【讨论】:

  • 正是我想要的!
  • 奇怪的是,该解决方案对我不起作用,因为 iPython 视图菜单保持不变。 (iPython 3.1.0)您的解决方案启发我进一步研究并找到p3trus 的一个非常相似的解决方案,它添加了一个按钮而不是菜单,并且确实有效。
  • @akhmed 也许你可以参考stackoverflow.com/a/29851084/1914781。这是一个不同的问题,但对你有帮助!
  • 这是给 jupyter 的。你仍然可以使用 RAW 而不是 markdown,看起来 Jupyter 不再使用 JQuery。包括来自您最喜欢的 CDN 的 script-JQuery。将 "$('div.input')" 更改为 "$('div.jp-Cell-inputArea')" 即可正常工作。
【解决方案6】:

这可以使用 IPython ToggleButton 小部件和一点 JavaScript 来完成。以下代码应放在文档顶部的代码单元格中:

import ipywidgets as widgets
from IPython.display import display, HTML

javascript_functions = {False: "hide()", True: "show()"}
button_descriptions  = {False: "Show code", True: "Hide code"}


def toggle_code(state):

    """
    Toggles the JavaScript show()/hide() function on the div.input element.
    """

    output_string = "<script>$(\"div.input\").{}</script>"
    output_args   = (javascript_functions[state],)
    output        = output_string.format(*output_args)

    display(HTML(output))


def button_action(value):

    """
    Calls the toggle_code function and updates the button description.
    """

    state = value.new

    toggle_code(state)

    value.owner.description = button_descriptions[state]


state = False
toggle_code(state)

button = widgets.ToggleButton(state, description = button_descriptions[state])
button.observe(button_action, "value")

display(button)

这将创建以下按钮来切换显示/隐藏 Jupyter Notebook 的代码,默认为“隐藏”状态:

当设置为“显示”状态时,您可以看到 Jupyter Notebook 的代码:

顺便说一句,虽然大部分代码应该放在 Notebook 的开头,但切换按钮的位置是可选的。就个人而言,我更喜欢将其保留在文档的底部。为此,只需将 display(button) 行移动到页面底部的单独代码单元格:

【讨论】:

    【解决方案7】:

    提供了一个不错的解决方案 here 适用于导出为 HTML 的笔记本。该网站甚至在此处链接回此 SO 帖子,但我在这里看不到 Chris 的解决方案! (克里斯,你在哪里?)

    这与来自harsil 的公认答案基本上是相同的解决方案,但它具有将切换代码本身隐藏在导出的HTML 中的优点。我也喜欢这种方法避免了对 IPython HTML 函数的需要。

    要实施此解决方案,请将以下代码添加到笔记本顶部的“原始 NBConvert”单元格中:

    <script>
      function code_toggle() {
        if (code_shown){
          $('div.input').hide('500');
          $('#toggleButton').val('Show Code')
        } else {
          $('div.input').show('500');
          $('#toggleButton').val('Hide Code')
        }
        code_shown = !code_shown
      }
    
      $( document ).ready(function(){
        code_shown=false;
        $('div.input').hide()
      });
    </script>
    <form action="javascript:code_toggle()">
      <input type="submit" id="toggleButton" value="Show Code">
    </form>
    

    然后只需将笔记本导出为 HTML。笔记本顶部会有一个切换按钮来显示或隐藏代码。

    Chris 还提供了一个示例 here

    我可以验证这在 Jupyter 5.0.0 中是否有效

    更新: 显示/隐藏div.prompt 元素以及div.input 元素也很方便。这将删除 In [##]:Out: [##] 文本并减少左侧的边距。

    【讨论】:

    • 是否可以使用此代码通过单击按钮选择性地隐藏输出? IE。 $('div.output').next().hide('500'); 隐藏下一个输出?我已经尝试过自己,但无法使其正常工作。
    【解决方案8】:

    在编辑界面和导出的 html 中显示/隐藏 Jupyter Notebook 代码单元的脚本

    只需将此代码放在第一个单元格中并运行它:

    %%HTML 
    <script>
        function luc21893_refresh_cell(cell) {
            if( cell.luc21893 ) return;
            cell.luc21893 = true;
            console.debug('New code cell found...' );
            
            var div = document.createElement('DIV');            
            cell.parentNode.insertBefore( div, cell.nextSibling );
            div.style.textAlign = 'right';
            var a = document.createElement('A');
            div.appendChild(a);
            a.href='#'
            a.luc21893 = cell;
            a.setAttribute( 'onclick', "luc21893_toggle(this); return false;" );
    
            cell.style.visibility='hidden';
            cell.style.position='absolute';
            a.innerHTML = '[show code]';        
                    
        }
        function luc21893_refresh() {                
            if( document.querySelector('.code_cell .input') == null ) {            
                // it apeears that I am in a exported html
                // hide this code
                var codeCells = document.querySelectorAll('.jp-InputArea')
                codeCells[0].style.visibility = 'hidden';
                codeCells[0].style.position = 'absolute';                        
                for( var i = 1; i < codeCells.length; i++ ) {
                    luc21893_refresh_cell(codeCells[i].parentNode)
                }
                window.onload = luc21893_refresh;
            }                 
            else {
                // it apperas that I am in a jupyter editor
                var codeCells = document.querySelectorAll('.code_cell .input')
                for( var i = 0; i < codeCells.length; i++ ) {
                    luc21893_refresh_cell(codeCells[i])
                }            
                window.setTimeout( luc21893_refresh, 1000 )
            }        
        }
        
        function luc21893_toggle(a) {
            if( a.luc21893.style.visibility=='hidden' ) {
                a.luc21893.style.visibility='visible';        
                a.luc21893.style.position='';
                a.innerHTML = '[hide code]';
            }
            else {
                a.luc21893.style.visibility='hidden';        
                a.luc21893.style.position='absolute';
                a.innerHTML = '[show code]';
            }
        }
        
        luc21893_refresh()
    </script>
    

    编辑器中的示例

    导出的 HTML 示例

    【讨论】:

    • 有没有办法添加标签来显示某些单元格的代码?
    【解决方案9】:

    为了更好地显示打印文档或报告,我们还需要移除按钮,以及显示或隐藏某些代码块的能力。这是我使用的(只需将其复制粘贴到您的第一个单元格):

    # This is a cell to hide code snippets from displaying
    # This must be at first cell!
    
    from IPython.display import HTML
    
    hide_me = ''
    HTML('''<script>
    code_show=true; 
    function code_toggle() {
      if (code_show) {
        $('div.input').each(function(id) {
          el = $(this).find('.cm-variable:first');
          if (id == 0 || el.text() == 'hide_me') {
            $(this).hide();
          }
        });
        $('div.output_prompt').css('opacity', 0);
      } else {
        $('div.input').each(function(id) {
          $(this).show();
        });
        $('div.output_prompt').css('opacity', 1);
      }
      code_show = !code_show
    } 
    $( document ).ready(code_toggle);
    </script>
    <form action="javascript:code_toggle()"><input style="opacity:0" type="submit" value="Click here to toggle on/off the raw code."></form>''')
    

    然后在你的下一个单元格中:

    hide_me
    print "this code will be hidden"
    

    print "this code will be shown"
    

    【讨论】:

    • 我猜这不适用于最新版本/python 3?
    • 适用于 jupyter 4.3.0 版和 Python 3.6.1 版。
    • 谢谢!很高兴地说这也适用于 Jupyter notebook 5.3.1。我正在使用 Python 版本 3.6.1
    【解决方案10】:

    这将呈现 IPython 笔记本输出。但是,您会注意到能够查看输入代码。您可以复制笔记本,然后在需要时添加此代码以与不需要查看代码的人共享。

    from IPython.display import HTML
    
    HTML('''<script> $('div .input').hide()''')
    

    【讨论】:

    • @Rocketq 使用这个 - from IPython.display import HTML HTML('''&lt;script&gt; $('div.input').show()''')
    【解决方案11】:

    将单元格转换为 Markdown 并使用 HTML5 &lt;details&gt; 标记,如 joyrexus 的示例:

    https://gist.github.com/joyrexus/16041f2426450e73f5df9391f7f7ae5f

    ## collapsible markdown?
    
    <details><summary>CLICK ME</summary>
    <p>
    
    #### yes, even hidden code blocks!
    
    ```python
    print("hello world!")
    ```
    
    </p>
    </details>
    

    【讨论】:

      【解决方案12】:
      jupyter nbconvert yourNotebook.ipynb --no-input --no-prompt
      

      jupyter nbconvert yourNotebook.ipynb 这部分代码会将jupyter notebook的latex文件格式转换成html

      --no-input这就像我们在转换过程中所说的不添加任何输入的参数:这里单元格的输入是代码..所以我们隐藏它

      --no-prompt 这里也是我们说的,在转换过程中不要在最终的 HTML 文件中显示任何提示,如错误或警告等代码),以便 html 仅以报告的形式输出文本和代码!!..

      希望对你有帮助:)

      【讨论】:

      • 请添加一些解释,而不是简单地用命令回答。
      • 你好,jupyter nbconvert yourNotebook.ipynb(这部分代码会把jupyter notebook的latex文件格式转换成html) --no-input(这就像我们的一个参数在转换过程中说不要添加任何输入:这里单元格的输入是代码..所以我们隐藏它)--no-prompt(这里我们也是说,在转换过程中不要显示任何来自代码的提示,如错误或最终 HTML 文件中的警告),以便该 html 将仅以报告的形式输出文本和代码!!.. 希望对您有所帮助:)
      【解决方案13】:

      使用浏览器的控制台非常简单的解决方案。您将其复制到浏览器控制台并按 Enter:

      $("div.input div.prompt_container").on('click', function(e){
          $($(e.target).closest('div.input').find('div.input_area')[0]).toggle();
      });
      

      然后您只需单击单元格输入的数量即可切换单元格的代码。

      【讨论】:

        【解决方案14】:

        Here 是一篇关于如何完善 Jpuyter(新的 IPython)笔记本以进行演示的好文章(与 @Ken 发布的相同)。有无数种方法可以使用 JS、HTML 和 CSS 扩展 Jupyter,包括通过 javascript 与 notebook 的 python 内核进行通信的能力。 %%HTML%%javascript 有魔法装饰器,所以你可以在一个单元格中自己做这样的事情:

        %%HTML
        <script>
          function code_toggle() {
            if (code_shown){
              $('div.input').hide('500');
              $('#toggleButton').val('Show Code')
            } else {
              $('div.input').show('500');
              $('#toggleButton').val('Hide Code')
            }
            code_shown = !code_shown
          }
        
          $( document ).ready(function(){
            code_shown=false;
            $('div.input').hide()
          });
        </script>
        <form action="javascript:code_toggle()"><input type="submit" id="toggleButton" value="Show Code"></form>
        

        我还可以保证 Chris 的方法在 jupyter 4.X.X 中有效。

        【讨论】:

          【解决方案15】:

          很多时候,我们需要在编写长代码时隐藏部分代码。

          示例:- 只需点击“代码显示/隐藏”,我们就可以隐藏 3 行代码。

          所以这里是你需要定义的函数来部分隐藏部分代码,然后在你想隐藏一些代码时调用它:

          from IPython.display import HTML
          
          def hide_toggle(for_next=False):
              this_cell = """$('div.cell.code_cell.rendered.selected')""" ; next_cell = this_cell + '.next()';
              toggle_text = 'Code show/hide'  # text shown on toggle link
              target_cell = this_cell ;  js_hide_current = '' 
          
              if for_next:
                  target_cell = next_cell; toggle_text += ' next cell';
                  js_hide_current = this_cell + '.find("div.input").hide();'
              js_f_name = 'code_toggle_{}'.format(str(random.randint(1,2**64)))
          
              html = """<script>
                      function {f_name}() {{{cell_selector}.find('div.input').toggle(); }}
                      {js_hide_current}
                  </script>
                  <a href="javascript:{f_name}()">{toggle_text}</a>
              """.format(f_name=js_f_name,cell_selector=target_cell,js_hide_current=js_hide_current, toggle_text=toggle_text )
              return HTML(html)
          

          一旦我们准备好函数定义,我们的下一个任务就很容易了。只是我们需要调用函数来隐藏/显示代码。

          print("Function for hiding the cell")
          hide_toggle()
          

          【讨论】:

            【解决方案16】:

            这是p3trus提出的另一种解决方案:

            $([IPython.events]).on('notebook_loaded.Notebook', function(){
                IPython.toolbar.add_buttons_group([
                    {
                         'label'   : 'toggle input cells',
                         'icon'    : 'icon-refresh', 
                         'callback': function(){$('.input').slideToggle()}
                    }
                ]);
            });
            

            p3trus 所述: "[It] 在 ipython 笔记本工具栏中添加一个按钮来隐藏/显示输入代码单元格。要使用它,您必须将 custom.js 文件放在您的 .ipython_&lt;profile name&gt;/static/custom/ 文件夹中,其中 是正在使用的 ipython 配置文件。”

            我自己的 cmets:我验证了这个解决方案,它适用于 iPython 3.1.0。

            【讨论】:

              【解决方案17】:

              经过以下修改,接受的解决方案也适用于 julia Jupyter/IJulia:

              display("text/html", """<script>
              code_show=true; 
              function code_toggle() {
               if (code_show){
               \$("div.input").hide();
               } else {
               \$("div.input").show();
               }
               code_show = !code_show
              } 
              \$( document ).ready(code_toggle);
              </script>
              <form action="javascript:code_toggle()"><input type="submit" value="Click here to toggle on/off the raw code."></form>""")
              

              特别注意:

              • 使用display函数
              • 转义 $ 符号(否则视为变量)

              【讨论】:

              • 我很困惑如何让它工作。是否需要导入语句以及块应该是什么类型的框。一个原始的还是一个代码框?
              【解决方案18】:

              使用上述所有解决方案,即使您隐藏了代码,您仍然会在您的身材上方看到[&lt;matplotlib.lines.Line2D at 0x128514278&gt;] 废话,这可能是您不想要的。

              如果你真的想摆脱输入而不是仅仅隐藏它,我想 最干净的解决方案是将您的图形保存到磁盘中的隐藏单元格中,然后使用例如将图像包含在 Markdown 单元格中。 ![Caption](figure1.png)

              【讨论】:

              • 你可以把_ = plt.plot()放到不打印[&lt;&gt;]废话
              • 在 matplotlib 绘图命令之后放置一个分号会抑制不需要的输出。
              【解决方案19】:
              jupyter nbconvert testing.ipynb --to html --no-input
              

              【讨论】:

                【解决方案20】:

                将笔记本导出为 HTML 的简单编程解决方案,无需代码单元(仅输出):将此代码添加到要导出的笔记本 my_notebook.ipynb 的代码单元中:

                import codecs
                import nbformat
                import time
                from IPython.display import Javascript
                from nbconvert import HTMLExporter
                
                def save_notebook():
                    display(
                        Javascript("IPython.notebook.save_notebook()"),
                        include=['application/javascript']
                    )    
                
                def html_export_output_only(read_file, output_file):
                    exporter = HTMLExporter()
                    exporter.exclude_input = True
                    output_notebook = nbformat.read(read_file, as_version=nbformat.NO_CONVERT)
                    output, resources = exporter.from_notebook_node(output_notebook)
                    codecs.open(output_file, 'w', encoding='utf-8').write(output)
                
                
                # save notebook to html
                save_notebook()
                time.sleep(1)
                output_file = 'my_notebook_export.html'
                html_export_output_only("my_notebook.ipynb", output_file)
                
                

                【讨论】:

                  【解决方案21】:

                  (纸张)打印或另存为 HTML

                  对于那些希望将输出打印到纸上的人来说,仅上述答案似乎并不能给出一个很好的最终输出。但是,使用@Max Masnick 的代码并添加以下代码可以将其打印在完整的 A4 页面上。

                  from IPython.display import display
                  from IPython.display import HTML
                  import IPython.core.display as di
                  
                  di.display_html('<script>jQuery(function() {if (jQuery("body.notebook_app").length == 0) { jQuery(".input_area").toggle(); jQuery(".prompt").toggle();}});</script>', raw=True)
                  
                  CSS = """#notebook div.output_subarea {max-width:100%;}""" #changes output_subarea width to 100% (from 100% - 14ex)
                  HTML('<style>{}</style>'.format(CSS))
                  

                  缩进的原因是 Max Masnick 删除的提示部分意味着输出时所有内容都向左移动。然而,这对限制为max-width:100%-14ex; 的输出的最大宽度没有任何作用。这会将 output_subarea 的最大宽度更改为 max-width:100%;

                  【讨论】:

                  • 您好,我不知道如何使它起作用。它根本不适合我。这就是投反对票的原因。
                  • 谢谢 - 我会看看并尝试更新它,这样它就可以了
                  猜你喜欢
                  • 2013-11-22
                  • 2014-11-05
                  • 1970-01-01
                  • 2014-09-09
                  • 2015-03-20
                  • 2022-07-03
                  • 2016-01-09
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多