tqdm ใน Jupyter Notebook จะพิมพ์แถบความคืบหน้าใหม่ซ้ำ ๆ


148

ฉันกำลังใช้tqdmเพื่อพิมพ์ความคืบหน้าในสคริปต์ที่ฉันใช้ในสมุดบันทึก Jupyter ฉันกำลังพิมพ์ข้อความทั้งหมดไปยังคอนโซลผ่านทางtqdm.write(). อย่างไรก็ตามสิ่งนี้ยังคงให้ผลลัพธ์ที่เบ้ฉันดังนี้:

ป้อนคำอธิบายภาพที่นี่

นั่นคือทุกครั้งที่ต้องพิมพ์บรรทัดใหม่จะมีการพิมพ์แถบความคืบหน้าใหม่ในบรรทัดถัดไป สิ่งนี้ไม่เกิดขึ้นเมื่อฉันเรียกใช้สคริปต์ผ่านเทอร์มินัล ฉันจะแก้ปัญหานี้ได้อย่างไร?


จริงๆแล้วตอนใช้tqdm_notebookฉันยังทำprints ปกติได้ด้วยและมันไม่มีผลกับแถบความคืบหน้า
Tomasz Gandor

อีกทางเลือกหนึ่งคือใช้progressbar stackoverflow.com/questions/3160699/python-progress-bar/…
eusoubrasileiro

คำตอบ:


231

ลองใช้tqdm.notebook.tqdmแทนtqdmดังที่ระบุไว้ที่นี่

ซึ่งอาจทำได้ง่ายเพียงแค่เปลี่ยนการนำเข้าของคุณเป็น:

from tqdm.notebook import tqdm

โชคดี!

แก้ไข:หลังจากการทดสอบดูเหมือนว่าtqdmจะใช้งานได้ดีใน 'โหมดข้อความ' ในสมุดบันทึก Jupyter เป็นการยากที่จะบอกได้เนื่องจากคุณไม่ได้ให้ตัวอย่างเล็กน้อยแต่ดูเหมือนว่าปัญหาของคุณจะเกิดจากคำสั่งพิมพ์ในการทำซ้ำแต่ละครั้ง คำสั่งการพิมพ์กำลังลบตัวเลข (~ 0.89) ระหว่างการอัปเดตแถบสถานะแต่ละรายการซึ่งทำให้เอาต์พุตสับสน ลองลบคำสั่งพิมพ์


2
ผมไม่ได้ใช้คำสั่งผมใช้print() tqdm.write()อย่างไรก็ตามtqdm_notebookให้ผลลัพธ์ที่ดี ขอบคุณ
:)

คุณรู้หรือไม่ว่ารองรับ Python 3.6 หรือไม่? ฉันไม่มีโชคกับสิ่งนี้
จอน

1
คุณได้รับข้อผิดพลาดอะไร มันใช้ได้ดีสำหรับฉัน เป็นไปไม่ได้ที่จะช่วยด้วยข้อมูลเพียงเล็กน้อย ... คุณเปิดใช้งาน ipywidgets ใน jupyerหรือไม่ คุณมีเพียงธรรมดาtqdmมากกว่าtqdm_notebook? ใช้งานได้ดีกับ Python 3.6 และ Jupyter 1.0.0
oscarbranson

tqdm_notebook จาก tqdm 4.19.4 ใช้งานได้สำหรับฉันบน Python 3.6, สมุดบันทึก Jupyter 5.0.0 และ ipywidgets 7.0.3
Matt Kleinsmith

2
@ bugmenot123 จับดีแก้ไข.
Czyzby

43

นี่เป็นคำตอบทางเลือกสำหรับกรณีที่tqdm_notebook ใช้ไม่ได้สำหรับคุณ

ให้ตัวอย่างต่อไปนี้:

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)

ผลลัพธ์จะมีลักษณะดังนี้ (ความคืบหน้าจะแสดงเป็นสีแดง):

  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

ปัญหาคือเอาต์พุตไปยังstdoutและstderrถูกประมวลผลแบบอะซิงโครนัสและแยกกันในรูปแบบของบรรทัดใหม่

ถ้าบอกว่า Jupyter ได้รับบน stderr บรรทัดแรกแล้วเอาต์พุต "ประมวลผล" บน stdout จากนั้นเมื่อได้รับเอาต์พุตบน stderr เพื่ออัปเดตความคืบหน้ามันจะไม่ย้อนกลับไปอัปเดตบรรทัดแรกเนื่องจากจะอัปเดตบรรทัดสุดท้ายเท่านั้น แต่จะต้องเขียนบรรทัดใหม่

วิธีแก้ปัญหาเบื้องต้น 1 เขียนถึง stdout

วิธีแก้ปัญหาอย่างหนึ่งคือการส่งออกทั้งคู่เป็น stdout แทน:

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)

ผลลัพธ์จะเปลี่ยนเป็น (ไม่มีสีแดงอีกต่อไป):

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]

ที่นี่เราจะเห็นว่า Jupyter ดูเหมือนจะไม่ชัดเจนจนกว่าจะถึงจุดสิ้นสุดของบรรทัด เราสามารถเพิ่มวิธีแก้ปัญหาอื่นได้โดยการเพิ่มช่องว่าง เช่น:

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)

ซึ่งทำให้เรา:

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

วิธีแก้ปัญหา 2 ตั้งค่าคำอธิบายแทน

โดยทั่วไปแล้วมันอาจจะตรงไปตรงมามากกว่าที่จะไม่มีเอาต์พุตสองเอาต์พุต แต่อัปเดตคำอธิบายแทนเช่น:

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)

ด้วยผลลัพธ์ (คำอธิบายอัปเดตขณะกำลังประมวลผล):

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

สรุป

คุณสามารถทำให้มันทำงานได้ดีด้วย tqdm ธรรมดา แต่ถ้าtqdm_notebookเหมาะกับคุณให้ใช้สิ่งนั้น (แต่คุณอาจจะไม่อ่านไกลขนาดนั้น)


อีกทางเลือกหนึ่งคือใช้progressbar stackoverflow.com/a/34482761/1207193
eusoubrasileiro

นี่คือคำตอบที่ดีที่สุด
Rafay

21

คำตอบส่วนใหญ่ล้าสมัยในขณะนี้ จะดีกว่าถ้าคุณนำเข้าtqdmอย่างถูกต้อง

from tqdm import tqdm_notebook as tqdm

ป้อนคำอธิบายภาพที่นี่


7
มันเปลี่ยนอีกแล้ว:TqdmDeprecationWarning: This function will be removed in tqdm==5.0.0 Please use tqdm.notebook.tqdm instead of tqdm.tqdm_notebook
stason

11

หากเคล็ดลับอื่น ๆ ที่นี่ใช้ไม่ได้ผลและเช่นเดียวกับฉัน - คุณกำลังใช้การpandasผสานรวมผ่านprogress_applyคุณสามารถtqdmจัดการได้:

from tqdm.autonotebook import tqdm
tqdm.pandas()

df.progress_apply(row_function, axis=1)

ประเด็นหลักอยู่ที่tqdm.autonotebookโมดูล ตามที่ระบุไว้ในคำแนะนำสำหรับการใช้งานในโน้ตบุ๊ก IPythonสิ่งนี้ทำให้tqdmเลือกระหว่างรูปแบบแถบความคืบหน้าที่ใช้ในโน้ตบุ๊ก Jupyter และคอนโซล Jupyter ด้วยเหตุผลที่ยังขาดการตรวจสอบเพิ่มเติมในฝั่งของฉันรูปแบบเฉพาะที่เลือกโดยใช้tqdm.autonotebookงานได้อย่างราบรื่นในpandasขณะที่รูปแบบอื่น ๆ ทั้งหมดไม่ได้ 't สำหรับprogress_applyโดยเฉพาะ


10

เพื่อให้คำตอบของ oscarbranson สมบูรณ์: สามารถเลือกแถบความคืบหน้าเวอร์ชันคอนโซลหรือโน้ตบุ๊กโดยอัตโนมัติขึ้นอยู่กับว่ากำลังเรียกใช้จากที่ใด

from tqdm.autonotebook import tqdm

สามารถดูข้อมูลเพิ่มเติมได้ที่นี่


8

ข้างต้นไม่ได้ผลสำหรับฉัน ฉันพบว่าการรันเพื่อติดตามปัญหานี้หลังจากเกิดข้อผิดพลาด (เพียงแค่ล้างอินสแตนซ์ทั้งหมดของแถบความคืบหน้าในพื้นหลัง):

from tqdm import tqdm

# blah blah your code errored

tqdm._instances.clear()

1
ขอบคุณ! อย่างไรก็ตามมันจะเกิดข้อผิดพลาดหากไม่มีอินสแตนซ์ ยังคงต้องการใช้กับสคริปต์และ Hydrogen IDE นี่คือรหัสของฉัน try: # Avoids problem on notebooks / Hydrogen IDE tqdm.tqdm._instances.clear() except Exception: pass
Jacques Peeters

ใช่มันจะทำให้เกิดข้อยกเว้นหากไม่มีอินสแตนซ์ มีปัญหากับการลองยกเว้นแนวทางของคุณหรือไม่?
James Owers

2

สำหรับทุกคนที่ใช้ windows และไม่สามารถแก้ปัญหาแถบที่ซ้ำกันด้วยวิธีแก้ไขปัญหาใด ๆ ที่กล่าวถึงที่นี่ ฉันต้องติดตั้งcoloramaแพ็คเกจตามที่ระบุไว้ในปัญหาที่ทราบของ tqdmซึ่งได้รับการแก้ไขแล้ว

pip install colorama

ลองใช้ตัวอย่างนี้:

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)

ซึ่งจะผลิตสิ่งต่างๆเช่น:

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.