tqdm
مشتق من الكلمة العربية تقدم (تقدم) والتي يمكن أن تعني "التقدم"، وهي اختصار لكلمة "أحبك كثيرًا" باللغة الإسبانية ( te quiero demasiado ).
اجعل حلقاتك تظهر على الفور مقياس تقدم ذكي - فقط قم بلف أي تكرار باستخدام tqdm(iterable)
، وبذلك تكون قد انتهيت!
from tqdm import tqdm
for i in tqdm ( range ( 10000 )):
...
76%|████████████████████████ | 7568/10000 [00:33<00:10, 229.00it/s]
يمكن أيضًا استخدام trange(N)
كاختصار مناسب لـ tqdm(range(N))
.
ويمكن أيضًا تنفيذها كوحدة نمطية باستخدام الأنابيب:
$ seq 9999999 | tqdm --bytes | wc -l
75.2MB [00:00, 217MB/s]
9999999
$ tar -zcf - docs/ | tqdm --bytes --total ` du -sb docs/ | cut -f1 `
> backup.tgz
32% | ██████████▍ | 8.89G/27.9G [00: 42< 01:31, 223MB/s]
الحمل منخفض - حوالي 60ns لكل تكرار (80ns مع tqdm.gui
)، ويتم اختبار الوحدة مقابل تراجع الأداء. بالمقارنة، فإن ProgressBar الراسخ لديه حمل قدره 800ns/iter.
بالإضافة إلى الحمل المنخفض، يستخدم tqdm
خوارزميات ذكية للتنبؤ بالوقت المتبقي وتخطي عروض التكرار غير الضرورية، مما يسمح بحمل لا يذكر في معظم الحالات.
يعمل tqdm
على أي نظام أساسي (Linux، وWindows، وMac، وFreeBSD، وNetBSD، وSolaris/SunOS)، وفي أي وحدة تحكم أو في واجهة المستخدم الرسومية، كما أنه متوافق مع أجهزة الكمبيوتر المحمولة IPython/Jupyter.
لا يتطلب tqdm
أي تبعيات (ولا حتى curses
!)، فقط Python وبيئة تدعم أحرف التحكم carriage return r
line feed n
.
جدول المحتويات
contrib
asyncio
logging
pip install tqdm
سحب وتثبيت فرع devel
:
pip install " git+https://github.com/tqdm/tqdm.git@devel#egg=tqdm "
conda install -c conda-forge tqdm
هناك 3 قنوات للاختيار من بينها:
snap install tqdm # implies --stable, i.e. latest tagged release
snap install tqdm --candidate # master branch
snap install tqdm --edge # devel branch
لاحظ أن الثنائيات snap
مخصصة فقط لاستخدام واجهة سطر الأوامر (غير قابلة import
)، وتقوم تلقائيًا بإعداد إكمال علامة تبويب bash
.
docker pull tqdm/tqdm
docker run -i --rm tqdm/tqdm --help
هناك أماكن أخرى (غير رسمية) حيث يمكن تنزيل tqdm
، خاصة لاستخدام سطر الأوامر:
قائمة جميع التغييرات متاحة إما على إصدارات GitHub: أو على الويكي أو على موقع الويب.
يعد tqdm
متعدد الاستخدامات ويمكن استخدامه بعدة طرق. الثلاثة الرئيسية مذكورة أدناه.
قم بلف tqdm()
حول أي قابل للتكرار:
from tqdm import tqdm
from time import sleep
text = ""
for char in tqdm ([ "a" , "b" , "c" , "d" ]):
sleep ( 0.25 )
text = text + char
trange(i)
هو مثيل خاص محسّن لـ tqdm(range(i))
:
from tqdm import trange
for i in trange ( 100 ):
sleep ( 0.01 )
يسمح إنشاء مثيل خارج الحلقة بالتحكم اليدوي في tqdm()
:
pbar = tqdm ([ "a" , "b" , "c" , "d" ])
for char in pbar :
sleep ( 0.25 )
pbar . set_description ( "Processing %s" % char )
التحكم اليدوي في تحديثات tqdm()
باستخدام عبارة with
:
with tqdm ( total = 100 ) as pbar :
for i in range ( 10 ):
sleep ( 0.1 )
pbar . update ( 10 )
إذا تم توفير المتغير الاختياري total
(أو متغير قابل للتكرار باستخدام len()
) ، فسيتم عرض الإحصائيات التنبؤية.
with
هو أيضًا اختياري (يمكنك فقط تعيين tqdm()
إلى متغير، ولكن في هذه الحالة لا تنسَ del
أو close()
في النهاية:
pbar = tqdm ( total = 100 )
for i in range ( 10 ):
sleep ( 0.1 )
pbar . update ( 10 )
pbar . close ()
ربما يكون الاستخدام الأكثر روعة لـ tqdm
هو في البرنامج النصي أو في سطر الأوامر. ما عليك سوى إدخال tqdm
(أو python -m tqdm
) بين الأنابيب سوف يمر عبر كل stdin
إلى stdout
أثناء تقدم الطباعة إلى stderr
.
يوضح المثال أدناه حساب عدد الأسطر في جميع ملفات Python في الدليل الحالي، مع تضمين معلومات التوقيت.
$ time find . -name ' *.py ' -type f -exec cat { } ; | wc -l
857365
real 0m3.458s
user 0m0.274s
sys 0m3.325s
$ time find . -name ' *.py ' -type f -exec cat { } ; | tqdm | wc -l
857366it [00:03, 246471.31it/s]
857365
real 0m3.585s
user 0m0.862s
sys 0m3.358s
لاحظ أنه يمكن أيضًا تحديد الوسائط المعتادة لـ tqdm
.
$ find . -name ' *.py ' -type f -exec cat { } ; |
tqdm --unit loc --unit_scale --total 857366 >> /dev/null
100% | █████████████████████████████████ | 857K/857K [00: 04< 00:00, 246Kloc/s]
النسخ الاحتياطي لدليل كبير؟
$ tar -zcf - docs/ | tqdm --bytes --total ` du -sb docs/ | cut -f1 `
> backup.tgz
44% | ██████████████▊ | 153M/352M [00: 14< 00:18, 11.0MB/s]
ويمكن تجميل هذا أكثر:
$ BYTES= $( du -sb docs/ | cut -f1 )
$ tar -cf - docs/
| tqdm --bytes --total " $BYTES " --desc Processing | gzip
| tqdm --bytes --total " $BYTES " --desc Compressed --position 1
> ~ /backup.tgz
Processing: 100% | ██████████████████████ | 352M/352M [00: 14< 00:00, 30.2MB/s]
Compressed: 42% | █████████▎ | 148M/352M [00: 14< 00:19, 10.9MB/s]
أو يتم ذلك على مستوى الملف باستخدام 7-zip:
$ 7z a -bd -r backup.7z docs/ | grep Compressing
| tqdm --total $( find docs/ -type f | wc -l ) --unit files
| grep -v Compressing
100% | ██████████████████████████▉ | 15327/15327 [01: 00< 00:00, 712.96files/s]
ستستفيد برامج CLI الموجودة مسبقًا والتي تنتج بالفعل معلومات التقدم الأساسية من علامتي --update
و --update_to
لـ tqdm
:
$ seq 3 0.1 5 | tqdm --total 5 --update_to --null
100% | ████████████████████████████████████ | 5.0/5 [00: 00< 00:00, 9673.21it/s]
$ seq 10 | tqdm --update --null # 1 + 2 + ... + 10 = 55 iterations
55it [00:00, 90006.52it/s]
تتعلق المشكلات الأكثر شيوعًا بالإفراط في الإنتاج على عدة أسطر، بدلاً من شريط التقدم الأنيق المكون من سطر واحد.
CR
, r
).r
بشكل صحيح (cloudwatch، K8s) من export TQDM_POSITION=-1
.colorama
في Python لضمان بقاء الأشرطة المتداخلة ضمن الخطوط الخاصة بها.ascii
فقط.tqdm
.tqdm(enumerate(...))
ب enumerate(tqdm(...))
أو tqdm(enumerate(x), total=len(x), ...)
. الأمر نفسه ينطبق على numpy.ndenumerate
.tqdm(zip(a, b))
بـ zip(tqdm(a), b)
أو حتى zip(tqdm(a), tqdm(b))
.itertools
.tqdm.contrib
.docker-compose run
بدلاً من docker-compose up
و tty: true
.export TQDM_MININTERVAL=5
لتجنب البريد العشوائي في السجل. تتم معالجة منطق التجاوز هذا بواسطة مصمم الديكور tqdm.utils.envwrap
(مفيد بشكل مستقل عن tqdm
).إذا واجهت أي صعوبات أخرى، تصفح واحفظ ملف .
(منذ 19 مايو 2016)
class tqdm ():
"""
Decorate an iterable object, returning an iterator which acts exactly
like the original iterable, but prints a dynamically updating
progressbar every time a value is requested.
"""
@ envwrap ( "TQDM_" ) # override defaults via env vars
def __init__ ( self , iterable = None , desc = None , total = None , leave = True ,
file = None , ncols = None , mininterval = 0.1 ,
maxinterval = 10.0 , miniters = None , ascii = None , disable = False ,
unit = 'it' , unit_scale = False , dynamic_ncols = False ,
smoothing = 0.3 , bar_format = None , initial = 0 , position = None ,
postfix = None , unit_divisor = 1000 , write_bytes = False ,
lock_args = None , nrows = None , colour = None , delay = 0 ):
يمكن تزيينه بشريط التقدم. اتركه فارغًا لإدارة التحديثات يدويًا.
بادئة لشريط التقدم.
عدد التكرارات المتوقعة إذا لم يكن محددًا، فسيتم استخدام len(iterable) إن أمكن. إذا كان float("inf") أو كملاذ أخير، فسيتم عرض إحصائيات التقدم الأساسية فقط (لا يوجد ETA، ولا يوجد شريط تقدم). إذا كانت gui
صحيحة وكانت هذه المعلمة تحتاج إلى تحديث لاحق، فحدد رقمًا موجبًا كبيرًا تعسفيًا أوليًا، على سبيل المثال 9e9.
إذا [افتراضي: صحيح]، فإنه يحتفظ بجميع آثار شريط التقدم عند انتهاء التكرار. إذا None
، فلن يغادر إلا إذا كان position
0
.
io.TextIOWrapper
أو io.StringIO
، اختياري يحدد مكان إخراج رسائل التقدم (الافتراضي: sys.stderr). يستخدم أساليب file.write(str)
و file.flush()
. للتشفير، راجع write_bytes
.
عرض رسالة الإخراج بأكملها. إذا تم تحديده، فسيتم تغيير حجم شريط التقدم ديناميكيًا ليبقى ضمن هذا الحد. إذا لم يتم تحديده، فسيحاول استخدام عرض البيئة. الاحتياطي هو عرض متر 10 وليس هناك حد للعداد والإحصائيات. إذا كانت 0، فلن تتم طباعة أي عداد (الإحصائيات فقط).
الحد الأدنى للفاصل الزمني لتحديث عرض التقدم [الافتراضي: 0.1] ثانية.
الحد الأقصى للفاصل الزمني لتحديث عرض التقدم [الافتراضي: 10] ثوانٍ. يقوم تلقائيًا بضبط miniters
لتتوافق مع mininterval
بعد تأخر تحديث العرض الطويل. يعمل فقط في حالة تمكين dynamic_miniters
أو مؤشر ترابط الشاشة.
الحد الأدنى للفاصل الزمني لتحديث عرض التقدم، في التكرارات. إذا كانت 0 و dynamic_miniters
، فسيتم ضبطهما تلقائيًا على mininterval
متساوية (أكثر كفاءة لوحدة المعالجة المركزية، جيدة للحلقات الضيقة). إذا كان > 0، فسيتم تخطي عرض العدد المحدد من التكرارات. قم بتعديل هذا والفاصل mininterval
للحصول على حلقات فعالة للغاية. إذا كان تقدمك غير منتظم مع كل من التكرارات السريعة والبطيئة (الشبكة، وتخطي العناصر، وما إلى ذلك)، فيجب عليك تعيين أجهزة miniters=1.
إذا كان غير محدد أو خطأ، استخدم Unicode (الكتل الناعمة) لملء جهاز القياس. الحل البديل هو استخدام أحرف ASCII "123456789#".
ما إذا كان سيتم تعطيل غلاف شريط التقدم بأكمله [الافتراضي: خطأ]. إذا تم التعيين على لا شيء، فقم بتعطيله على الأجهزة التي لا تستخدم أجهزة TTY.
السلسلة التي سيتم استخدامها لتحديد وحدة كل تكرار [الافتراضي: it].
إذا كانت 1 أو True، فسيتم تقليل/قياس عدد التكرارات تلقائيًا وستتم إضافة بادئة مترية تتبع معيار النظام الدولي للوحدات (كيلو، ميجا، وما إلى ذلك) [الافتراضي: خطأ]. إذا كان هناك أي رقم آخر غير الصفر، فسيتم قياس total
و n
.
إذا تم ضبطه، فسيقوم باستمرار بتغيير ncols
و nrows
إلى البيئة (مما يسمح بتغيير حجم النافذة) [افتراضي: False].
عامل تمهيد المتوسط المتحرك الأسي لتقديرات السرعة (يتم تجاهله في وضع واجهة المستخدم الرسومية). يتراوح من 0 (متوسط السرعة) إلى 1 (السرعة الحالية/اللحظية) [الافتراضي: 0.3].
تحديد تنسيق سلسلة شريطية مخصصة. قد يؤثر على الأداء. [افتراضي: '{l_bar}{bar}{r_bar}']، حيث l_bar='{desc}: {percentage:3.0f}%|' و r_bar = '| {n_fmt}/{total_fmt} [{elapsed<{remaining}, ' '{rate_fmt}{postfix}]' المتغيرات المحتملة: l_bar، bar، r_bar، n، n_fmt، الإجمالي، Total_fmt، النسبة المئوية، المنقضي، المنقضي_s، ncols ، نروز، تنازلي، وحدة، معدل، معدل_فمت، معدل_نوينف، Rate_noinv_fmt، Rate_inv، Rate_inv_fmt، Postfix، Unit_divisor، المتبقي، المتبقي، ETA. لاحظ أنه تتم إزالة ": " تلقائيًا بعد {desc} إذا كان الأخير فارغًا.
قيمة العداد الأولية. مفيد عند إعادة تشغيل شريط التقدم [الافتراضي: 0]. في حالة استخدام float، فكر في تحديد {n:.3f}
أو ما شابه ذلك في bar_format
، أو تحديد unit_scale
.
حدد إزاحة الخط لطباعة هذا الشريط (بدءًا من 0) تلقائيًا إذا لم يتم تحديده. من المفيد إدارة أشرطة متعددة في وقت واحد (على سبيل المثال، من المواضيع).
*
اختياري حدد إحصائيات إضافية لعرضها في نهاية الشريط. يستدعي set_postfix(**postfix)
إن أمكن (dict).
[الافتراضي: 1000]، يتم تجاهله إلا إذا كانت unit_scale
صحيحة.
سواء لكتابة بايت. إذا (الافتراضي: خطأ) سوف يكتب يونيكود.
تم تمريره refresh
للمخرجات المتوسطة (التهيئة، والتكرار، والتحديث).
ارتفاع الشاشة. إذا تم تحديده، فإنه يخفي الأشرطة المتداخلة خارج هذا الحد. إذا لم يتم تحديده، فسيحاول استخدام ارتفاع البيئة. الاحتياطي هو 20.
لون الشريط (على سبيل المثال، "أخضر"، "#00ff00").
لا يتم العرض حتى انقضاء [الافتراضي: 0] ثانية.
delim
.delim
، وتحديد unit_scale
الافتراضي إلى True، و unit_divisor
إلى 1024، و unit
إلى 'B'.stdin
إلى كل من stderr
و stdout
.update()
. لاحظ أن هذا بطيء (~2e5 it/s) حيث يجب فك تشفير كل إدخال كرقم.self.n
. لاحظ أن هذا بطيء (~2e5 it/s) حيث يجب فك تشفير كل إدخال كرقم. class tqdm ():
def update ( self , n = 1 ):
"""
Manually update the progress bar, useful for streams
such as reading files.
E.g.:
>>> t = tqdm(total=filesize) # Initialise
>>> for current_buffer in stream:
... ...
... t.update(len(current_buffer))
>>> t.close()
The last line is highly recommended, but possibly not necessary if
``t.update()`` will be called in such a way that ``filesize`` will be
exactly reached and printed.
Parameters
----------
n : int or float, optional
Increment to add to the internal counter of iterations
[default: 1]. If using float, consider specifying ``{n:.3f}``
or similar in ``bar_format``, or specifying ``unit_scale``.
Returns
-------
out : bool or None
True if a ``display()`` was triggered.
"""
def close ( self ):
"""Cleanup and (if leave=False) close the progressbar."""
def clear ( self , nomove = False ):
"""Clear current bar display."""
def refresh ( self ):
"""
Force refresh the display of this bar.
Parameters
----------
nolock : bool, optional
If ``True``, does not lock.
If [default: ``False``]: calls ``acquire()`` on internal lock.
lock_args : tuple, optional
Passed to internal lock's ``acquire()``.
If specified, will only ``display()`` if ``acquire()`` returns ``True``.
"""
def unpause ( self ):
"""Restart tqdm timer from last print time."""
def reset ( self , total = None ):
"""
Resets to 0 iterations for repeated use.
Consider combining with ``leave=True``.
Parameters
----------
total : int or float, optional. Total to use for the new bar.
"""
def set_description ( self , desc = None , refresh = True ):
"""
Set/modify description of the progress bar.
Parameters
----------
desc : str, optional
refresh : bool, optional
Forces refresh [default: True].
"""
def set_postfix ( self , ordered_dict = None , refresh = True , ** tqdm_kwargs ):
"""
Set/modify postfix (additional stats)
with automatic formatting based on datatype.
Parameters
----------
ordered_dict : dict or OrderedDict, optional
refresh : bool, optional
Forces refresh [default: True].
kwargs : dict, optional
"""
@ classmethod
def write ( cls , s , file = sys . stdout , end = " n " ):
"""Print a message via tqdm (without overlap with bars)."""
@ property
def format_dict ( self ):
"""Public API for read-only member access."""
def display ( self , msg = None , pos = None ):
"""
Use ``self.sp`` to display ``msg`` in the specified ``pos``.
Consider overloading this function when inheriting to use e.g.:
``self.some_frontend(**self.format_dict)`` instead of ``self.sp``.
Parameters
----------
msg : str, optional. What to display (default: ``repr(self)``).
pos : int, optional. Position to ``moveto``
(default: ``abs(self.pos)``).
"""
@ classmethod
@ contextmanager
def wrapattr ( cls , stream , method , total = None , bytes = True , ** tqdm_kwargs ):
"""
stream : file-like object.
method : str, "read" or "write". The result of ``read()`` and
the first argument of ``write()`` should have a ``len()``.
>>> with tqdm.wrapattr(file_obj, "read", total=file_obj.size) as fobj:
... while True:
... chunk = fobj.read(chunk_size)
... if not chunk:
... break
"""
@ classmethod
def pandas ( cls , * targs , ** tqdm_kwargs ):
"""Registers the current `tqdm` class with `pandas`."""
def trange ( * args , ** tqdm_kwargs ):
"""Shortcut for `tqdm(range(*args), **tqdm_kwargs)`."""
def tqdm . contrib . tenumerate ( iterable , start = 0 , total = None ,
tqdm_class = tqdm . auto . tqdm , ** tqdm_kwargs ):
"""Equivalent of `numpy.ndenumerate` or builtin `enumerate`."""
def tqdm . contrib . tzip ( iter1 , * iter2plus , ** tqdm_kwargs ):
"""Equivalent of builtin `zip`."""
def tqdm . contrib . tmap ( function , * sequences , ** tqdm_kwargs ):
"""Equivalent of builtin `map`."""
class tqdm . notebook . tqdm ( tqdm . tqdm ):
"""IPython/Jupyter Notebook widget."""
class tqdm . auto . tqdm ( tqdm . tqdm ):
"""Automatically chooses beween `tqdm.notebook` and `tqdm.tqdm`."""
class tqdm . asyncio . tqdm ( tqdm . tqdm ):
"""Asynchronous version."""
@ classmethod
def as_completed ( cls , fs , * , loop = None , timeout = None , total = None ,
** tqdm_kwargs ):
"""Wrapper for `asyncio.as_completed`."""
class tqdm . gui . tqdm ( tqdm . tqdm ):
"""Matplotlib GUI version."""
class tqdm . tk . tqdm ( tqdm . tqdm ):
"""Tkinter GUI version."""
class tqdm . rich . tqdm ( tqdm . tqdm ):
"""`rich.progress` version."""
class tqdm . keras . TqdmCallback ( keras . callbacks . Callback ):
"""Keras callback for epoch and batch progress."""
class tqdm . dask . TqdmCallback ( dask . callbacks . Callback ):
"""Dask callback for task progress."""
contrib
تحتوي الحزمة tqdm.contrib
أيضًا على وحدات تجريبية:
tqdm.contrib.itertools
: أغلفة رقيقة حول itertools
tqdm.contrib.concurrent
: أغلفة رقيقة حول concurrent.futures
tqdm.contrib.slack
: المشاركات في روبوتات Slacktqdm.contrib.discord
: المشاركات في روبوتات Discordtqdm.contrib.telegram
: المشاركات في روبوتات Telegramtqdm.contrib.bells
: تمكين كافة الميزات الاختيارية تلقائيًاauto
pandas
slack
discord
telegram
help()
; يمكن عرض المعلومات المخصصة وتحديثها ديناميكيًا على أشرطة tqdm
باستخدام الوسيطتين desc
و postfix
:
from tqdm import tqdm , trange
from random import random , randint
from time import sleep
with trange ( 10 ) as t :
for i in t :
# Description will be displayed on the left
t . set_description ( 'GEN %i' % i )
# Postfix will be displayed on the right,
# formatted automatically based on argument's datatype
t . set_postfix ( loss = random (), gen = randint ( 1 , 999 ), str = 'h' ,
lst = [ 1 , 2 ])
sleep ( 0.1 )
with tqdm ( total = 10 , bar_format = "{postfix[0]} {postfix[1][value]:>8.2g}" ,
postfix = [ "Batch" , { "value" : 0 }]) as t :
for i in range ( 10 ):
sleep ( 0.1 )
t . postfix [ 1 ][ "value" ] = i / 2
t . update ()
نقاط يجب تذكرها عند استخدام {postfix[...]}
في سلسلة bar_format
:
postfix
أيضًا إلى تمريره كوسيطة أولية بتنسيق متوافق، وpostfix
تلقائيًا إلى سلسلة إذا كان كائنًا يشبه dict
. لمنع هذا السلوك، قم بإدراج عنصر إضافي في القاموس حيث المفتاح ليس سلسلة. يمكن أيضًا تعريف معلمات bar_format
الإضافية عن طريق تجاوز format_dict
، ويمكن تعديل الشريط نفسه باستخدام ascii
:
from tqdm import tqdm
class TqdmExtraFormat ( tqdm ):
"""Provides a `total_time` format parameter"""
@ property
def format_dict ( self ):
d = super (). format_dict
total_time = d [ "elapsed" ] * ( d [ "total" ] or 0 ) / max ( d [ "n" ], 1 )
d . update ( total_time = self . format_interval ( total_time ) + " in total" )
return d
for i in TqdmExtraFormat (
range (