tqdm in Jupyter Notebook druckt wiederholt neue Fortschrittsbalken

138

Ich verwende tqdm, um den Fortschritt in einem Skript zu drucken, das ich in einem Jupyter-Notizbuch ausführe. Ich drucke alle Nachrichten über an die Konsoletqdm.write() . Dies gibt mir jedoch immer noch eine verzerrte Ausgabe wie folgt:

Geben Sie hier die Bildbeschreibung ein

Das heißt, jedes Mal, wenn eine neue Zeile gedruckt werden muss, wird in der nächsten Zeile ein neuer Fortschrittsbalken gedruckt. Dies passiert nicht, wenn ich das Skript über das Terminal ausführe. Wie kann ich das lösen?

Rohan Saxena
quelle
Wenn ich es benutze tqdm_notebook, kann ich sogar normale prints machen, und es hat keinen Einfluss auf den Fortschrittsbalken.
Tomasz Gandor
Eine Alternative ist die Verwendung dieses progressbar stackoverflow.com/questions/3160699/python-progress-bar/…
eusoubrasileiro

Antworten:

216

Versuchen Sie es mit tqdm.notebook.tqdmanstelle von tqdm, wie hier beschrieben .

Dies kann so einfach sein wie das Ändern Ihres Imports in:

from tqdm.notebook import tqdm

Viel Glück!

BEARBEITEN: Nach dem Testen scheint es, dass es tqdmim 'Textmodus' in Jupyter Notebook tatsächlich gut funktioniert. Es ist schwer zu sagen, da Sie kein minimales Beispiel angegeben haben , aber es sieht so aus, als ob Ihr Problem durch eine print-Anweisung in jeder Iteration verursacht wird. Die print-Anweisung gibt zwischen jeder Statusleistenaktualisierung eine Zahl (~ 0,89) aus, wodurch die Ausgabe durcheinander gebracht wird. Versuchen Sie, die print-Anweisung zu entfernen.

oscarbranson
quelle
2
Ich habe keine print()Aussage verwendet, ich habe verwendet tqdm.write(). Allerdings tqdm_notebookgibt gute Ergebnisse. Danke
:)
Wissen Sie, ob es Python 3.6 unterstützt? Ich hatte kein Glück damit
Jon
1
Welchen Fehler bekommen Sie? Es funktioniert gut für mich. Es ist unmöglich, mit so wenig Informationen zu helfen ... Haben Sie ipywidgets in jupyer aktiviert ? Hast du tqdmeher einfach als tqdm_notebook? Dies funktioniert gut mit Python 3.6 und Jupyter 1.0.0.
Oscarbranson
tqdm_notebook von tqdm 4.19.4 funktioniert für mich unter Python 3.6, Jupyter Notebook 5.0.0 und ipywidgets 7.0.3.
Matt Kleinsmith
2
@ bugmenot123 Guter Fang, behoben.
Czyzby
39

Dies ist eine alternative Antwort für den Fall, dass tqdm_notebook für Sie nicht funktioniert.

Anhand des folgenden Beispiels:

from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values)) as pbar:
    for i in values:
        pbar.write('processed: %d' %i)
        pbar.update(1)
        sleep(1)

Die Ausgabe würde ungefähr so ​​aussehen (Fortschritt würde rot angezeigt):

  0%|          | 0/3 [00:00<?, ?it/s]
processed: 1
 67%|██████▋   | 2/3 [00:01<00:00,  1.99it/s]
processed: 2
100%|██████████| 3/3 [00:02<00:00,  1.53it/s]
processed: 3

Das Problem ist, dass die Ausgabe an stdout und stderr asynchron und getrennt in Bezug auf neue Zeilen verarbeitet wird.

Wenn sagen, Jupyter empfängt auf stderr die erste Zeile und dann die "verarbeitete" Ausgabe auf stdout. Sobald es eine Ausgabe auf stderr erhält, um den Fortschritt zu aktualisieren, würde es nicht zurückgehen und die erste Zeile aktualisieren, da es nur die letzte Zeile aktualisieren würde. Stattdessen muss eine neue Zeile geschrieben werden.

Problemumgehung 1, Schreiben an stdout

Eine Problemumgehung wäre, stattdessen beide in stdout auszugeben:

import sys
from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
    for i in values:
        pbar.write('processed: %d' % (1 + i))
        pbar.update(1)
        sleep(1)

Die Ausgabe ändert sich zu (nicht mehr rot):

processed: 1   | 0/3 [00:00<?, ?it/s]
processed: 2   | 0/3 [00:00<?, ?it/s]
processed: 3   | 2/3 [00:01<00:00,  1.99it/s]
100%|██████████| 3/3 [00:02<00:00,  1.53it/s]

Hier können wir sehen, dass Jupyter erst am Ende der Zeile zu klären scheint. Wir könnten eine weitere Problemumgehung hinzufügen, indem wir Leerzeichen hinzufügen. Sowie:

import sys
from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
    for i in values:
        pbar.write('processed: %d%s' % (1 + i, ' ' * 50))
        pbar.update(1)
        sleep(1)

Was uns gibt:

processed: 1                                                  
processed: 2                                                  
processed: 3                                                  
100%|██████████| 3/3 [00:02<00:00,  1.53it/s]

Problemumgehung 2: Legen Sie stattdessen die Beschreibung fest

Im Allgemeinen ist es möglicherweise einfacher, nicht zwei Ausgänge zu haben, sondern stattdessen die Beschreibung zu aktualisieren, z.

import sys
from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
    for i in values:
        pbar.set_description('processed: %d' % (1 + i))
        pbar.update(1)
        sleep(1)

Mit der Ausgabe (Beschreibung während der Verarbeitung aktualisiert):

processed: 3: 100%|██████████| 3/3 [00:02<00:00,  1.53it/s]

Fazit

Sie können es meistens mit normalem tqdm zum Laufen bringen. Aber wenn tqdm_notebook für Sie funktioniert, verwenden Sie das einfach (aber dann würden Sie wahrscheinlich nicht so weit lesen).

de1
quelle
Eine Alternative ist die Verwendung dieses progressbar stackoverflow.com/a/34482761/1207193
eusoubrasileiro
Dies ist bei weitem die beste Antwort.
Rafay
18

Die meisten Antworten sind jetzt veraltet. Besser, wenn Sie tqdm korrekt importieren .

from tqdm import tqdm_notebook as tqdm

Geben Sie hier die Bildbeschreibung ein

Shritam Kumar Mund
quelle
7
Es änderte sich wieder:TqdmDeprecationWarning: This function will be removed in tqdm==5.0.0 Please use tqdm.notebook.tqdm instead of tqdm.tqdm_notebook
Stason
10

Wenn die anderen Tipps hier nicht funktionieren und Sie - genau wie ich - die pandasIntegration verwenden progress_apply, können Sie sich damit tqdmbefassen:

from tqdm.autonotebook import tqdm
tqdm.pandas()

df.progress_apply(row_function, axis=1)

Der Hauptpunkt liegt hier im tqdm.autonotebookModul. Wie in angegeben in IPython Notebooks ihre Anweisungen für die Verwendung , das macht tqdmwählen zwischen verschiedenen Formaten Fortschrittsbalken verwendet in Jupyter Notebooks und Jupyter Konsolen - für einen Grund , noch weitere Untersuchungen an meiner Seite fehlt, von der gewählten spezifischen Format tqdm.autonotebookfunktioniert reibungslos pandas, während alle anderen didn nicht progress_applyspeziell.

Julio Cezar Silva
quelle
9

Um die Antwort von oscarbranson zu vervollständigen: Es ist möglich, automatisch Konsolen- oder Notebook-Versionen des Fortschrittsbalkens auszuwählen, je nachdem, von wo aus es ausgeführt wird:

from tqdm.autonotebook import tqdm

Weitere Infos finden Sie hier

mjarosie
quelle
8

Keines der oben genannten funktioniert für mich. Ich finde, dass das Ausführen von Folgendem dieses Problem nach einem Fehler sortiert (es löscht nur alle Instanzen von Fortschrittsbalken im Hintergrund):

from tqdm import tqdm

# blah blah your code errored

tqdm._instances.clear()
James Owers
quelle
1
Danke dir! Es wird jedoch ein Fehler ausgelöst, wenn keine Instanzen vorhanden sind. Ich möchte es weiterhin mit Skripten und der Wasserstoff-IDE verwenden. Hier ist mein Code. try: # Avoids problem on notebooks / Hydrogen IDE tqdm.tqdm._instances.clear() except Exception: pass
Jacques Peeters
Ja, es wird eine Ausnahme ausgelöst, wenn keine Instanz vorhanden ist. Gibt es ein Problem mit Ihrem Versuch außer Ansatz?
James Owers
0

Verwenden Sie tqdm_notebook

aus tqdm importiere tqdm_notebook als tqdm

x = [1,2,3,4,5]

für i in tqdm (len (x)):

print(x[i])
Kranthi Kumar Valaboju
quelle
0

Für alle, die unter Windows arbeiten und das Problem der Duplizierungsbalken mit keiner der hier genannten Lösungen lösen konnten. Ich musste das coloramaPaket wie in den bekannten Problemen von tqdm beschrieben installieren, die es behoben haben.

pip install colorama

Versuchen Sie es mit diesem Beispiel:

from tqdm import tqdm
from time import sleep

for _ in tqdm(range(5), "All", ncols = 80, position = 0):
    for _ in tqdm(range(100), "Sub", ncols = 80, position = 1, leave = False):
        sleep(0.01)

Welches wird so etwas wie produzieren:

All:  60%|████████████████████████                | 3/5 [00:03<00:02,  1.02s/it]
Sub:  50%|██████████████████▌                  | 50/100 [00:00<00:00, 97.88it/s]
Nebel
quelle