"sample larger than population" in random.sample python

Since the python_3.6 you can use random.choices(x, k=v) for your purpose. It returns a k sized list of elements chosen from the population with replacement. If the population is empty, raises IndexError.


@Martijn Pieters is right. But since they state at https://docs.python.org/3.4/library/random.html:

Warning: The pseudo-random generators of this module should not be used for security purposes. Use os.urandom() or SystemRandom if you require a cryptographically secure pseudo-random number generator.

and the purpose of this is for generating passwords, I suggest this approach:

import string
import random

set = string.letters + string.digits + string.punctuation
length = 20

password = ''.join( [ random.SystemRandom().choice( set) for _ in range( length) ] )

print( password)

Could anybody please confirm that this is more secure?


The purpose of random.sample() is to pick a subset of the input sequence, randomly, without picking any one element more than once. If your input sequence has no repetitions, neither will your output.

You are not looking for a subset; you want single random choices from the input sequence, repeated a number of times. Elements can be used more than once. Use random.choice() in a loop for this:

for i in range(y):
    string = ''.join([random.choice(x) for _ in range(v)])
    print string

This creates a string of length v, where characters from x can be used more than once.

Quick demo:

>>> import string
>>> import random
>>> x = string.letters + string.digits + string.punctuation
>>> v = 20
>>> ''.join([random.choice(x) for _ in range(v)])
'Ms>V\\0Mf|W@R,#/.P~Rv'
>>> ''.join([random.choice(x) for _ in range(v)])
'TsPnvN&qlm#mBj-!~}3W'
>>> ''.join([random.choice(x) for _ in range(v)])
'{:dfE;VhR:=_~O*,QG<f'