Jak ukryć kod przed komórkami w notatniku ipython wizualizowanym za pomocą nbviewer?

147

Mam notatnik ipython / jupyter, który wizualizuję za pomocą NBviewer.

Jak mogę ukryć cały kod z notatnika wyrenderowanego przez NBviewer, tak aby wyświetlane były tylko dane wyjściowe kodu (np. Wykresy i tabele) oraz komórki przecen?

lucacerone
źródło
10
Nadal nie ma do tego przycisku w domyślnym interfejsie użytkownika (luty 2016 r.). IMHO to jest naprawdę irytujące. To jest na liście funkcji, które zostaną zaimplementowane: github.com/jupyter/notebook/issues/534 To świetnie. Czekam na to z niecierpliwością.
stochastic
1
Proszę spojrzeć poniżej na odpowiedź Noego. Dzięki dołączeniu TemplateExporter ten problem jest rozwiązany niezależnie od formatu wyjściowego. W chwili pisania tego tekstu odpowiedź Noego zastępuje trudną odpowiedź (co było dobrym rozwiązaniem dla TemplateExportera).
MichaelA

Odpowiedzi:

235
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>''')
ostry
źródło
5
Pracował dla mnie na iPythonie 3.1.0, jeśli umieściłem go w komórce kodu. Zastąpiłem <form action ... > ... </form>prostym The raw code for this IPython notebook is by default hidden for easier reading.To toggle on/off the raw code, click <a href="javascript:code_toggle()">here</a>.
kodem
Dziękuję za Twoją odpowiedź! Zobacz moją odpowiedź, jeśli chcesz, aby przycisk był ukryty i możliwość ukrywania lub pokazywania niektórych bloków kodu, takich jak Rstudio.
kod jaycode
3
Dzięki, to działa i przy „zapisywaniu w html”. Zalecamy umieszczenie tego w swojej własnej komórce na górze notebooka.
Vivek Gani
jeśli dodasz atrybut accesskey = "h" do elementu wejściowego, możesz następnie wykonać show hide za pomocą alt-h (przynajmniej w chrome)
frankc
7
Jak byś to zmienił, żeby nawet nie pokazywał przycisku, a jedynie ukrywał kod?
Harlekuin
79

Jest to teraz możliwe bezpośrednio z nbconvert od wersji 5.2.1 : zawartość można filtrować za pomocą wbudowanych opcji wykluczania eksportera szablonów . Na przykład:

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

wykluczy komórki „input code”, tj. sam kod. Podobne opcjeIstnieją , aby wykluczyć monity, komórki przecen lub wyjścia albo zarówno dane wejściowe, jak i wyjściowe.

(Te opcje powinny działać niezależnie od formatu wyjściowego).

Noe
źródło
3
to najlepsza odpowiedź
skurp
Gdzie domyślnie zapisywany jest eksport .pdf?
MyopicVisage
Ten sam folder co notatnik .ipython. Użyj argumentu „--output NotebookNoCode”, aby zmienić nazwę pliku.
MyopicVisage
Czy to ma działać w notebooku?
lcrmorin
@were_cat nie, to jest polecenie powłoki używane do eksportowania pliku notatnika .ipynb; w tym przykładzie jest konwertowany do formatu pdf
Noah,
19

użyłbym hide_input_all z nbextensions ( https://github.com/ipython-contrib/IPython-notebook-extensions ). Oto jak:

  1. Dowiedz się, gdzie jest twój katalog IPython:

    from IPython.utils.path import get_ipython_dir
    print get_ipython_dir()
  2. Pobierz nbextensions i przenieś je do katalogu IPython.

  3. Edytuj plik custom.js gdzieś w katalogu IPython (mój był w profile_default / static / custom ), aby był podobny do pliku custom.example.js w katalogu nbextensions .

  4. Dodaj tę linię do custom.js :

    IPython.load_extensions('usability/hide_input_all')

Notatnik IPython będzie miał teraz przycisk do przełączania komórek kodu, niezależnie od skoroszytu.

user394430
źródło
6
Właśnie tego spróbowałem - wydaje się, że pomaga to ukryć komórki kodu podczas edycji notatnika, chociaż podczas zapisywania notatnika do html (tj. Renderowania do nbviewer) komórki kodu nadal się pojawiają.
Vivek Gani
@VivekGani tylko krótka uwaga, że ​​możesz ukryć ukryte komórki w wyeksportowanym html za pomocą szablonu dostarczonego z tym samym repozytorium, zobacz odpowiednią stronę dokumentu (również zobacz to odpowiednie pytanie )
glS
15

Najnowsza wersja notatnika IPython nie pozwala już na wykonywanie javascript w komórkach markdown, więc dodanie nowej komórki markdown z następującym kodem javascript nie będzie już działać, aby ukryć komórki kodu (patrz ten link )

Zmień ~ / .ipython / profile_default / static / custom / custom.js, jak poniżej:

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>")
});
Yangshun Tay
źródło
dokładnie to, czego szukam!
lucky1928
O dziwo, to rozwiązanie nie zadziałało, ponieważ menu widoku iPythona pozostaje niezmienione. (iPython 3.1.0) Twoje rozwiązanie zainspirowało mnie do dalszych poszukiwań i znalezienia bardzo podobnego rozwiązania przez p3trus, które dodało przycisk zamiast menu i zadziałało.
akhmed
1
@akhmed Może możesz odnieść się do stackoverflow.com/a/29851084/1914781 . To pytanie o różnicę, ale jest pomocne dla Ciebie!
12

Napisałem kod, który to robi i dodaje przycisk do przełączania widoczności kodu.

Poniższe informacje znajdują się w komórce kodu u góry notatnika:

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)

Możesz zobaczyć przykład, jak to wygląda w NBviewer tutaj .

Aktualizacja: Będzie to miało trochę zabawne zachowanie w przypadku komórek Markdown w Jupyter, ale działa dobrze w wersji eksportowej HTML notatnika.

Max Masnick
źródło
3
Działa to na komórkach kodu, ale jeśli masz komórki przecenowe, robi to coś dziwnego. Pokazuje przecenę jako przecenę , a następnie pokazuje tę samą treść - ale sformatowaną - poniżej.
Scott H
Właśnie się zorientowałem, że jedyną nieprawidłową rzeczą jest specyfikacja węzła. Zamiast '.input_area'i '.prompt', używaj 'div.input'i działa jak urok! Podsumowując, zastąp jQuery("div.input").toggle();w miejsce jQuery('.input_area').toggle(); jQuery('.prompt').toggle();. @Max Masnick, czy mógłbyś poprawić swoją odpowiedź?
Scott H
Używanie "div.input" jako wyboru węzła działa tak długo, jak długo nie wchodzisz w interakcję z komórkami przecen, ale właśnie doszedłem do wniosku, że jeśli wejdziesz w interakcję z komórkami przecen, możesz uzyskać dziwne zachowanie. Na przykład, jeśli klikniesz dwukrotnie komórkę przeceny, zostanie ona całkowicie ukryta. Tak więc moje ulepszenie rozwiązania Maxa jest dobre do generowania HTML do udostępniania innym, ale nie do późniejszej interakcji z nim za dużo.
Scott H
Tak, więc zauważyłem to samo, co zrobiłeś, gdy wszystkie komórki Markdown zostały podniesione. Działa dobrze w eksporcie HTML, gdzie go używam. Zmienię odpowiedź, aby to zanotować.
Max Masnick
1
Aby usunąć pozostałą spację po usunięciu „.prompt”, po prostu dodaj ten kod na końcu powyższego kodu. CSS = """#notebook div.output_subarea { max-width:100%;""" HTML('<style>{}</style>'.format(CSS)). Jest to bardzo przydatne podczas drukowania.
Little Bobby Tables
10

Można to zrobić za pomocą ToggleButtonwidżetu IPython i odrobiny JavaScript. Poniższy kod należy umieścić w komórce kodu u góry dokumentu:

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)

Spowoduje to utworzenie następującego przycisku służącego do przełączania wyświetlania / ukrywania kodu notatnika Jupyter, domyślnie ustawionego na stan „ukryj”:

Ukryj stan kodu

Po ustawieniu stanu „pokaż” można zobaczyć kod notatnika Jupyter:

Pokaż stan kodu

Nawiasem mówiąc, chociaż znaczna część tego kodu powinna być umieszczona na początku Notatnika, położenie przycisku przełącznika jest opcjonalne. Osobiście wolę trzymać go u dołu dokumentu. Aby to zrobić, po prostu przenieś display(button)wiersz do oddzielnej komórki kodu u dołu strony:

Przeniesiony przycisk przełącznika

Erick Shepherd
źródło
9

Istnieje rozwiązanie ładny pod warunkiem tutaj które działa dobrze w przypadku notatników eksportowanych do HTML. Witryna zawiera nawet linki do tego posta SO, ale nie widzę tutaj rozwiązania Chrisa! (Chris, gdzie jesteś?)

Jest to w zasadzie to samo rozwiązanie, co zaakceptowana odpowiedź od harshil, ale ma tę zaletę, że ukrywa sam kod przełączania w eksportowanym HTML. Podoba mi się również to, że takie podejście pozwala uniknąć konieczności korzystania z funkcji HTML IPython.

Aby wdrożyć to rozwiązanie, dodaj następujący kod do komórki „Raw NBConvert” u góry notatnika:

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

Następnie po prostu wyeksportuj notatnik do formatu HTML. W górnej części notatnika pojawi się przycisk przełączania, aby pokazać lub ukryć kod.

Chris również podaje tutaj przykład .

Mogę sprawdzić, czy to działa w Jupyter 5.0.0

Aktualizacja : Wygodne jest również pokazywanie / ukrywanie div.promptelementów wraz z div.inputelementami. Usuwa In [##]:i Out: [##]tekst i zmniejsza marże na lewo.

Rozpoznać
źródło
czy byłoby możliwe użycie tego kodu do selektywnego ukrywania danych wyjściowych jednym kliknięciem przycisku? IE $('div.output').next().hide('500');ukryć następny wynik? Próbowałem sam, ale nie mogę tego uruchomić.
Brian Keith
7

Aby lepiej wyświetlać wydrukowany dokument lub raport, musimy również usunąć przycisk i możliwość pokazywania lub ukrywania niektórych bloków kodu. Oto czego używam (po prostu skopiuj i wklej to do swojej pierwszej komórki):

# 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>''')

Następnie w kolejnych komórkach:

hide_me
print "this code will be hidden"

i

print "this code will be shown"
jaycode
źródło
Zgaduję, że to nie działa w przypadku najnowszych wersji / Python 3?
baxx
Działa z jupyter w wersji 4.3.0 z Pythonem w wersji 3.6.1.
Alma Rahat
Dzięki! Z przyjemnością mogę powiedzieć, że działa to również z notebookiem Jupyter 5.3.1 . Używam Pythona w wersji 3.6.1
Amitrajit Bose
4

Spowoduje to wygenerowanie danych wyjściowych notatnika IPython. Zauważysz jednak, że będziesz w stanie wyświetlić kod wejściowy. Możesz skopiować notatnik, a następnie w razie potrzeby dodać ten kod, aby udostępnić go komuś, kto nie musi go wyświetlać.

from IPython.display import HTML

HTML('''<script> $('div .input').hide()''')
Ścigaj Wrighta
źródło
1
@Rocketq użyj tego - from IPython.display import HTML HTML('''<script> $('div.input').show()''')
fixxxer
4

Przekonwertuj komórkę na Markdown i użyj <details>tagu HTML5, jak w przykładzie 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>
Valentas
źródło
1

Oto kolejne rozwiązanie sugerowane przez p3trus :

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

Jak opisano w p3trus : „[It] dodaje przycisk do paska narzędzi notatnika ipython, aby ukryć / pokazać komórkę kodu wejściowego. Aby go użyć, musisz umieścić plik custom.js w swoim.ipython_<profile name>/static/custom/ folderze, gdzie to używany profil ipython. "

Moje własne uwagi: Zweryfikowałem to rozwiązanie i działa z iPythonem 3.1.0.

akhmed
źródło
1

Przyjęte rozwiązanie działa również w julia Jupyter / IJulia z następującymi modyfikacjami:

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

w szczególności uwaga:

  • użyj displayfunkcji
  • uciec przed $znakiem (inaczej postrzegane jako zmienna)
gozzilli
źródło
Nie wiem, jak to działa. Czy potrzebna jest instrukcja importu i jaki typ pudełka powinien być blok. Surowy czy skrzynka kodowa?
J Spen
1

Oto fajny artykuł (ten sam, który opublikował @Ken) o tym, jak dopracować notebooki Jpuyter (nowy IPython) do prezentacji. Istnieje niezliczona ilość sposobów na rozszerzenie Jupyter za pomocą JS, HTML i CSS, w tym możliwość komunikacji z jądrem Pythona notebooka z poziomu javascript. Istnieją magiczne dla dekoratorów %%HTMLi %%javascriptwięc można po prostu zrobić coś takiego w komórce przez siebie:

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

Mogę również ręczyć, że metody Chrisa działają w jupyter 4.XX

ThisGuyCantEven
źródło
1

Bardzo proste rozwiązanie przy użyciu konsoli przeglądarki. Kopiujesz to do konsoli przeglądarki i wciskasz enter:

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

wstaw skrypt do konsoli przeglądarki

Następnie przełączasz kod komórki, po prostu klikając liczbę danych wejściowych komórki.

numer komórki

Matěj M
źródło
0

(Papier) Drukowanie lub zapisywanie jako HTML

Dla tych z Was, którzy chcą wydrukować wyniki na papierze, same powyższe odpowiedzi wydają się nie dawać ładnego wyniku końcowego. Jednak wzięcie kodu @Max Masnick i dodanie następującego pozwala wydrukować go na pełnej stronie 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))

Powodem wcięcia jest to, że sekcja zachęty usunięta przez Maxa Masnicka oznacza, że ​​wszystko przesuwa się w lewo na wyjściu. Nie wpłynęło to jednak na maksymalną szerokość wyjścia, do której było ograniczone max-width:100%-14ex;. Zmienia to maksymalną szerokość output_subarea na max-width:100%;.

Stoły Little Bobby
źródło
0

Dzięki wszystkim powyższym rozwiązaniom, mimo że ukrywasz kod, nadal otrzymasz [<matplotlib.lines.Line2D at 0x128514278>] bzdury nad swoją figurą, których prawdopodobnie nie chcesz.

Jeśli faktycznie chcesz pozbyć się danych wejściowych, a nie tylko je ukrywać, myślę, że najczystszym rozwiązaniem jest zapisanie swoich figur na dysku w ukrytych komórkach, a następnie po prostu dołączenie obrazów w komórkach Markdown za pomocą np ![Caption](figure1.png).

maxymoo
źródło
3
Możesz położyć, _ = plt.plot()aby nie drukować [<>]bzdur
jonnybazookatone
3
Umieszczenie średnika po poleceniach kreślących matplotlib zablokowało niechciane dane wyjściowe.
DakotaD
0
jupyter nbconvert testing.ipynb --to html --no-input
gocode
źródło
0
jupyter nbconvert yourNotebook.ipynb --no-input --no-prompt
Naveen Kumar
źródło
6
Zamiast odpowiadać poleceniem, dodaj wyjaśnienie.
Fabian Bettag