0

I'm attempting to generate all the possible passwords with lengths between 1-5 characters, where the possible characters are the lowercase alphabet, uppercase alphabet and 10 digits.

For the sake of keeping things simple, I'm restricting the possible characters to just the lowercase alphabet and the ten digits, and the lengths of the passwords to just 3-5 characters.

import itertools
charMix = list("abcdefghijklmnopqrstuvwxyz1234567890")
mix = []
for length in range(3, 6):
   temp = [''.join(p) for p in itertools.product(charMix, repeat=length)]
   mix.append(temp)

However, I'm running into memory errors on the temp assignment line and don't know how to overcome them :(

Is there a way to generate these passwords without memory errors?

martineau
  • 119,623
  • 25
  • 170
  • 301
Adi219
  • 4,712
  • 2
  • 20
  • 43
  • 1
    You're dealing with around 2 gigabytes of data, even with your restricted alphabet & length. Ideally, you wouldn't store the entire list of passwords at all - you'd do whatever you need to do with each password as it is generated. – jasonharper Jul 18 '19 at 16:42
  • Possible duplicate of [Python generate all possible strings of length n](https://stackoverflow.com/questions/43119744/python-generate-all-possible-strings-of-length-n) – Alexander Santos Jul 18 '19 at 16:51
  • @jasonharper For 36^5, I get around 60 million entries, each 5 characters long would make 300 MB of data. I'm in no way a python guy, so maybe I'm missing the obvious. Nonetheless I would agree, that in most cases you just need a mapping from numbers to password and a counter, at which number from the 60 millions you are. – user unknown Jul 22 '19 at 11:35

1 Answers1

1

Since you actually mention the term generate, consider a generator here if that will satisfy your use case:

from typing import Generator
import itertools

def make_pws(join="".join) -> Generator[str, None, None]:
    charMix = "abcdefghijklmnopqrstuvwxyz1234567890"
    for length in range(3, 6):
       for p in itertools.product(charMix, repeat=length):
           yield join(p)

You can iterate through this result like a sequence without placing the entire contents in memory:

>>> pws = make_pws()
>>> next(pws)
'aaa'
>>> next(pws)
'aab'
>>> next(pws)
'aac'
>>> next(pws)
'aad'
>>> for pw in make_pws():
...     # process each one at a time
Brad Solomon
  • 38,521
  • 31
  • 149
  • 235
  • Thanks; I decided on a similar route since there weren't any answers but this is essentially what I realised and implemented as well so thanks :) – Adi219 Jul 18 '19 at 17:17