python_pardus
python_pardus

Reputation: 320

How to Avoid MemoryError About Permutations in Python

I'm writing a simple rar/zip cracking program. For cracking their passwords, I prepared a permutation command. But when I run these codes:

>>> import itertools
>>> o = itertools.permutations("abcdefghijklmnoprstuvyzwxq1234567890_", 10)
>>> a = list(o)

I got this error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
MemoryError

Upvotes: 2

Views: 1981

Answers (2)

jsbueno
jsbueno

Reputation: 110311

Don't create a "list" of the permutations. The "permutations" call is a special construct tat will generate one permutation at a time - the idea is that you consume it, and then retrieve the next value.

When you do

>>> a = list(o)

You want to record all values at once in memory -which does not suffice in this case.

As a side note - if you do generate one permutation at a time in your particular example, you won run out of memory, but you, your computer, the Solar system and the Universe in general will run out of time, as the number of combinations for 10 elements out of 30 or so is beyond astronomical.

Upvotes: 2

Aleksandr Kovalev
Aleksandr Kovalev

Reputation: 3734

UPD:

First of all, you should use product function from itertools module instead of permutations if you want to get all possible passwords from this alphabet.

Also, if you want to increase speed of execution, you should use multiprocessing module instead of threading.

You may achieve your goal this way, for example:

from itertools import product, islice
from multiprocessing import Pool

def crack(list_of_tuples):
    for letters in list_of_tuples:
        password = ''.join(letters)
        success = try_to_crack(password)
        if success:
            print('password is {}'.format(password))
            break

tuples = product('abcdefghijklmnoprstuvyzwxq1234567890_', repeat=10)

size_of_slice = 5000
number_of_processes = 8
running = True
while running:
    p = Pool(number_of_processes)
    slices = []
    for i in range(number_of_processes):
        l = list(islice(tuples, size_of_slice))
        if l:
            slices.append(l)
        else:
            running = False
    p.map(crack, slices)

See also multiprocessing-vs-threading

Original answer:

Don't create a list, just use it as it is:

permutations = itertools.permutations("abcdefghijklmnoprstuvyzwxq1234567890_", 10)
for permutation in permutations:
    password = ''.join(permutation)
    success = try_to_crack(password)
    if success:
        print('password is {}'.format(password))
        break

Upvotes: 4

Related Questions