#1810·tqdm

`tqdm.pandas`: empty DataFrame raises `ZeroDivisionError`, and `total=` only applies once

Author: yayong3Created Sep 3, 2026Updated Sep 3, 2026
  • I have marked all applicable categories:
    • exception-raising bug
    • visual output bug
  • I have visited the source website, and in particular read the known issues
  • I have searched through the issue tracker for duplicates
  • I have mentioned version numbers, operating system and environment, where applicable:
    python
    import tqdm, sys
    print(tqdm.__version__, sys.version, sys.platform)

Summary

There are two bugs in tqdm.pandas()'s shared inner closure, empty dataFrames and total= is consumed after the first call.

Empty DataFrames

description For a non-grouped DataFrame, the total is calculated as total = df.size // df.shape[axis]. This divides by zero for a DataFrame with no rows when axis=0, or no columns when axis=1. Pandas accepts both cases, but progress_apply fails before calling DataFrame.apply.

Reproduction

python
import pandas as pd
from tqdm import tqdm

tqdm.pandas()
df = pd.DataFrame(columns=["a", "b"])
df.progress_apply(lambda column: column)

Output:

Traceback (most recent call last):
  File "/home/test02.py", line 7, in <module>
    df.progress_apply(lambda column: column)
  File "/tqdm/tqdm/std.py", line 884, in inner
    total = df.size // df.shape[axis]
            ~~~~~~~~^^~~~~~~~~~~~~~~~
ZeroDivisionError: integer division or modulo by zero

total is consumed after the first call

description tqdm.pandas(total=123) The total parameter passed in should have been valid for each subsequent progress_apply call, but the current implementation removes it from the shared dictionary during the first call.

Reproduction

from io import StringIO
import pandas as pd
from tqdm import tqdm
output = StringIO()
tqdm.pandas(
    file=output, ascii=True, leave=True, total=123,
    mininterval=0, miniters=1)

pd.Series([10, 20, 30]).progress_apply(lambda value: value + 1)
print(output.getvalue().replace("\r", "\n").strip().split("\n")[-1])
output.seek(0)
output.truncate(0)
pd.Series([10, 20, 30, 40]).progress_apply(lambda value: value + 1)
print(output.getvalue().replace("\r", "\n").strip().split("\n")[-1])

Output

  2%|2         | 3/123 [00:00<00:00, 6790.56it/s]
100%|##########| 4/4 [00:00<00:00, 6820.01it/s]

The first line reports 3/123; the second reports 4/4. I would expect the configured total to remain in effect until tqdm.pandas() is called again.

Environment

Python 3.12.3 (main, Jun 19 2026, 12:46:00) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tqdm, sys
>>> print(tqdm.__version__, sys.version, sys.platform)
4.70.0 3.12.3 (main, Jun 19 2026, 12:46:00) [GCC 13.3.0] linux