Как скрыть код от ячеек в блокноте ipython, визуализированных с помощью nbviewer?

У меня есть записная книжка ipython/jupyter, которую я визуализирую с помощью NBviewer.

Как я могу скрыть весь код из записной книжки, созданной NBviewer, чтобы отображались только выходные данные кода (например, графики и таблицы) и ячейки уценки?

24 ответа

Решение
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>''')

Теперь это возможно напрямую из nbconvert начиная с версии 5.2.1: контент можно фильтровать с помощью встроенного в экспортер шаблонов параметров exclude. Например:

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

исключит ячейки "входного кода", то есть сам код. Аналогичные параметры существуют для исключения приглашений, ячеек уценки или выходов, а также входов и выходов.

(Эти параметры должны работать независимо от формата вывода.)

Я хотел бы использовать hide_input_all от nbextensions ( https://github.com/ipython-contrib/IPython-notebook-extensions). Вот как:

  1. Узнайте, где находится ваш каталог IPython:

    from IPython.utils.path import get_ipython_dir
    print get_ipython_dir()
    
  2. Загрузите nbextensions и переместите его в каталог IPython.

  3. Отредактируйте файл custom.js где-нибудь в каталоге IPython (мой был в profile_default / static / custom), чтобы он был похож нафайл custom.example.js в каталоге nbextensions.

  4. Добавьте эту строку в custom.js:

    IPython.load_extensions('usability/hide_input_all')
    

В IPython Notebook теперь есть кнопка для переключения ячеек кода независимо от рабочей книги.

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

В ячейку кода в верхней части записной книжки входит следующее:

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)

Вы можете увидеть пример того, как это выглядит в NBviewer здесь.

Обновление: это будет иметь забавное поведение с ячейками Markdown в Jupyter, но оно отлично работает в HTML-версии ноутбука.

Новейшая версия записной книжки IPython больше не позволяет выполнять javascript в ячейках уценки, поэтому добавление новой ячейки уценки со следующим кодом javascript больше не будет работать, чтобы скрыть ячейки кода (см. Эту ссылку)

Измените ~/.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 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, установленного по умолчанию в состояние "скрыть":

Скрыть кодовое состояние

Когда вы установите состояние "show", вы сможете увидеть код для Jupyter Notebook:

Показать состояние кода

Кроме того, хотя большая часть этого кода должна быть размещена в начале ноутбука, расположение кнопки переключения не является обязательным. Лично я предпочитаю держать это в нижней части документа. Для этого просто переместите display(button) строка в отдельной ячейке кода внизу страницы:

Перемещенная кнопка переключения

Скрипт для отображения / скрытия ячеек кода Jupyter Notebook как в интерфейсе редактирования, так и в экспортированном HTML

Просто поместите этот код в первую ячейку и запустите его:

      %%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

Здесь представлено хорошее решение, которое хорошо работает для ноутбуков, экспортируемых в HTML. Веб-сайт даже ссылается сюда на этот пост, но я не вижу решения Криса здесь! (Крис, где ты?)

Это в основном то же решение, что и принятый от harshil ответ, но его преимущество заключается в том, что он скрывает сам код переключения в экспортированном HTML. Мне также нравится, что этот подход устраняет необходимость в HTML-функции IPython.

Чтобы реализовать это решение, добавьте следующий код в ячейку "Raw 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. В верхней части записной книжки будет кнопка для отображения или скрытия кода.

Крис также приводит пример здесь.

Я могу убедиться, что это работает в Jupyter 5.0.0

Обновление: также удобно показать / скрыть div.prompt элементы наряду с div.input элементы. Это удаляет In [##]: а также Out: [##] текст и уменьшает поля слева.

Для лучшего отображения с напечатанным документом или отчетом нам также необходимо удалить кнопку и возможность показать или скрыть определенные блоки кода. Вот что я использую (просто скопируйте и вставьте это в свою первую ячейку):

# 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"

Конвертируйте ячейку в Markdown и используйте HTML5 <details> пометить как в примере 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>
jupyter nbconvert yourNotebook.ipynb --no-input --no-prompt

Это отобразит вывод записной книжки IPython. Тем не менее, вы заметите, сможете просматривать входной код. Вы можете скопировать блокнот, а затем добавить этот код, если это необходимо, чтобы поделиться с кем-то, кому не нужно просматривать код.

from IPython.display import HTML

HTML('''<script> $('div .input').hide()''')

Очень простое решение с использованием Консоли браузера. Вы копируете это в консоль своего браузера и нажимаете ввод:

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

Затем вы переключаете код ячейки, просто щелкая по номеру ввода ячейки.

Используйте Runtools, который расширяет базовый ноутбук iPython:

https://github.com/ipython-contrib/IPython-notebook-extensions/wiki/Runtools

Часто нам нужно скрыть некоторые части кода при написании длинного кода.

Пример: - Просто нажав "Показать / скрыть код", мы можем скрыть 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()

Вот хорошая статья (написанная @Ken) о том, как полировать блокноты Jpuyter (новый IPython) для презентации. Существует множество способов расширить Jupyter с помощью JS, HTML и CSS, включая возможность взаимодействия с ядром python ноутбука из javascript. Есть волшебные декораторы для %%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>

Я также могу поручиться работе Криса в Jupyter 4.XX

Вот еще одно решение, предложенное 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: "[Он] добавляет кнопку на панель инструментов ноутбука ipython, чтобы скрыть / показать ячейку входного кода. Чтобы использовать ее, вы должны поместить файл custom.js в свой файл. .ipython_<profile name>/static/custom/ папка, где используется профиль ipython. "

Мои собственные комментарии: я проверил это решение, и оно работает с iPython 3.1.0.

Принятое решение также работает в Юлии Юпитер /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 функция
  • избежать $ знак (иначе рассматривается как переменная)

Если вы работаете вручную (без массового запуска/массового экспорта), есть довольно простое решение: добавьте следующий блок кода и выполните его.

      from IPython.core.display import HTML
HTML('<style>.input, .jp-InputArea {display: none !important}</style>')

Код исчезнет как в «обычном» интерфейсе, так и в режиме предварительного просмотра/экспорта в HTML. Очистите вывод этой одной ячейки, чтобы вернуть код, готово

Обратите внимание, что код все еще там , просто не виден, поэтому используйте его только тогда, когда вы хотите показать (или экспортировать, использовать предварительный просмотр для создания PDF-файла. Этот PDF-файл теперь выглядит довольно прилично. Не используйте его, если вы хотите сохранить код для сам)

Проблема, с которой я столкнулся с ответом @harshil, user4244561 том, что он не свернет скрытые ячейки, оставив на их месте несколько некрасиво выглядящее пустое пространство (я использую IPython 7.30.1 и nbconvert 6.3.0) . заключается [пример]

Это связано с тем, что div находится внутри оболочки, поэтому, когда она скрыта, оболочка не рушится. (Если у вас нет ячеек кода без вывода, это не будет для вас проблемой, т.к. скрыт, он схлопнется внутри обертки, и поэтому div займет все место).

Вот как вы можете это сделать (просто поместите это в ячейку):

      from IPython.display import HTML

HTML('''<script>
    var code_show = true; 
    function code_toggle() {
         if (code_show) {
             $( 'div[class*="code_cell"]:not(:has(.output))' ).hide();
             $( 'div.input' ).hide();
         } else {
             $( 'div[class*="code_cell"]:not(:has(.output))' ).show();
             $( 'div.input' ).show();
         }
         code_show = !code_show;
    } 
    $( document ).ready(code_toggle);
    </script>
    To toggle on/off the raw code, click <a>href="javascript:code_toggle()">here</a>.''')
jupyter nbconvert testing.ipynb --to html --no-input

(Бумага) Печать или сохранение в формате 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-width:100%-14ex;, Это изменяет максимальную ширину output_subarea на max-width:100%;,

Со всеми вышеупомянутыми решениями, даже если вы скрываете код, вы все равно получите [<matplotlib.lines.Line2D at 0x128514278>] дерьмо над вашей фигурой, которую вы, вероятно, не хотите.

Если вы действительно хотите избавиться от ввода, а не просто скрыть его, я думаю, что самое чистое решение - сохранить ваши фигуры на диске в скрытых ячейках, а затем просто включить изображения в ячейки Markdown, используя, например, ![Caption](figure1.png),

Простое программное решение для экспорта записной книжки в 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)

Другие вопросы по тегам