Dominik1123 ยท GitHub

Bug report

Bug description:

I just encountered the situation where I used random.sample but both the population and counts arguments were empty (my algorithm had nothing left to choose from). So, basically this situation:

>>> random.sample([], 1, counts=[])
Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
    random.sample([], 1, counts=[])
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/path/to/lib/python3.14/random.py", line 424, in sample
    total = cum_counts.pop()
IndexError: pop from empty list

Instead of the IndexError, I expected a ValueError, similar to the following situations:

>>> random.sample([], 1)
Traceback (most recent call last):
  File "<python-input-2>", line 1, in <module>
    random.sample([], 1)
    ~~~~~~~~~~~~~^^^^^^^
  File "/path/to/lib/python3.14/random.py", line 434, in sample
    raise ValueError("Sample larger than population or is negative")
ValueError: Sample larger than population or is negative
>>>
>>> random.sample([1], 2, counts=[1])
Traceback (most recent call last):
  File "<python-input-3>", line 1, in <module>
    random.sample([1], 2, counts=[1])
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "/path/to/lib/python3.14/random.py", line 429, in sample
    selections = self.sample(range(total), k=k)
  File "/path/to/lib/python3.14/random.py", line 434, in sample
    raise ValueError("Sample larger than population or is negative")
ValueError: Sample larger than population or is negative

The docs mention that

If the sample size is larger than the population size, a ValueError is raised.

In addition, I would expect the following to work:

>>> random.sample([], 0, counts=[])
Traceback (most recent call last):
  File "<python-input-4>", line 1, in <module>
    random.sample([], 0, counts=[])
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/path/to/lib/python3.14/random.py", line 424, in sample
    total = cum_counts.pop()
IndexError: pop from empty list

similar to how it works when counts is not specified:

>>> random.sample([], 0)
[]

Not sure though what CPython's backwards-compatibility policy has to say here, since changing the exception type โ€“ or, in the second case, removing the exception altogether โ€“ might actually break someone's code...


Tested with:

Python 3.14.0a5 (main, Feb 12 2025, 14:51:40) [Clang 19.1.6 ] on linux
cpython-3.14.0a5-linux-x86_64-gnu

CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs

Read the original on github.com โ†—