如何过滤python的itertools的product函数中生成的某些组合?

abithluo  于 2023-05-19  发布在  Python
关注(0)|答案(2)|浏览(164)

我正在使用python的itertools模块,通过它的product函数,编写一个密码生成程序,我试图生成唯一 * 的密码,这些密码没有已经保存在我的数据库中。
问题是:当我试图生成更多的密码,我需要等待一个地狱的时间!对于新的密码出来,我已经写了代码来过滤已经在数据库中的密码
但是**product函数仍然处理密码,即使它们已经被使用,然后它打印出还没有使用的密码,这仍然需要同样的时间,这太多了!现在我知道我可以使用我的GPU来完成这个过程,但我确信必须有一个逻辑操作来阻止这个函数生成已经使用过的密码。
下面是源代码(不要太注意代码的其他部分,我知道它本身不能工作,因为我正在另一种master main程序中使用这个Generator函数):

from string import *
from itertools import product

# The password generator function.
# a little detail about the parameters:
# From = password starts from how many characters
# To = password ends with how many characters
# Fname = stands for 'file name' which is actually the database name
# cn, Base = these are just to organize different databases, not too much important in this case
def Generator(From, To, Fname, cn, Base):
    # Defining the database
    global db
    db = Fname+cn+'.txt'
    # Listing all the already used passwords in the 'lines' list
    global lines
    lines = []
    mainDB = open(Fname+str(Base)+'.txt')
    lines = mainDB.readlines()
    mainDB.close()
    # Defining the characters which (probably) can't be used as passwords(due to injection attacks and so on...)
    Blocked = ",:?/\\|<>*"+"'"+'"'
    # The ones that i'm not sure if they have to be blocked... but i'm blocking them anyway :|
    proBlocked = ";[]{}()+=^`"
    Blocked += proBlocked
    chars = ascii_letters + digits + punctuation
    # Deleting all the blocked characters from the main 'chars' string
    for c in Blocked:
        chars = chars.replace(c,'')

    # Going for generating the password trying every single password we can make and take a unique one out for use
    for i in range(From,To):
        # Starting the `product` module which is the main element of the program
        for j in product(chars, repeat=i):
            # Defining the 'word' container(or the 'password' container if you will)
            global word
            # Putting the generated word in the container(variable)
            word = "".join(j)
            # Opening the database
            p = open(db, '+r')
            # Checking if the password has already been used and added to the main database
            if not(word in str(lines)):
                # Adding to the database and returning the unique password
                p.write(p.read() + word + '\n')
                p.close()
                return word

下面是主程序:

from Generator import Generator
import os
import sys

# This part needs some more work, like designing and so on
# right now we're just testing.
while True:
    os.system('cls')
    inp = input("Type 1 to start generating, or type 0 to close the program:\n")
    if inp.isdigit():
        if inp == '1':
            break
        elif inp == '0':
            sys.exit()

print("Here's your unique password: "+Generator(4, 10, "MainDB", 1, 1))

下面是程序的输出:

Type 1 to start generating, or type 0 to close the program:
1
Here's your unique password: aaaa

现在,通过过滤数据库中的更多密码,密码不会像'aaaa'这样的东西,它们会更好,有时意味着一些东西,可以记住(而不是使用随机的,因为我已经有一个程序)
真的很感谢你的帮助<3再次,问题是:我正在寻找一种方法来过滤产品模块本身已经使用的密码,以阻止那些甚至生成,以保存大量的时间。
先谢谢你了!

lokaqttq

lokaqttq1#

“过滤掉已经使用过的密码”实际上是检查product函数的输出是否与一些使用过的密码集相匹配。(即使您编写了自己的特殊“product_with_exclusions”函数,它也需要这样工作。
您的代码已经执行了此检查,但可以使其更快。在对product的结果进行循环的每次迭代时,问题中的代码将密码列表转换为字符串,并检查输出。反复转换list -> str并检查密码是否是那个大字符串的一部分是很慢的。最好是(1)不转换为str,(2)使用set而不是list(与相同大小的列表相比,检查值是否在大集合中要快得多)。
这样,优化后的代码看起来就像这样。(这包括一些其他的整理-删除不必要的全局变量,在打开文件时与-block一起使用,并在追加模式下写入新密码。

from string import *
from itertools import product

# The password generator function.
# a little detail about the parameters:
# From = password starts from how many characters
# To = password ends with how many characters
# Fname = stands for 'file name' which is actually the database name
# cn, Base = these are just to organize different databases, not too much important in this case
def Generator(From, To, Fname, cn, Base):
    # Defining the database
    db = Fname+cn+'.txt'
    
    # Listing all the already used passwords in the 'lines_set' set for fast lookup
    with open(Fname+str(Base)+'.txt') as mainDB:
        lines_set = {l.strip() for l in mainDB.readlines()}

    # Defining the characters which (probably) can't be used as passwords(due to injection attacks and so on...)
    Blocked = ",:?/\\|<>*"+"'"+'"'
    
    # The ones that i'm not sure if they have to be blocked... but i'm blocking them anyway :|
    proBlocked = ";[]{}()+=^`"
    Blocked += proBlocked
    chars = ascii_letters + digits + punctuation
    
    # Deleting all the blocked characters from the main 'chars' string
    chars = [c for c in chars if c not in Blocked]

    # Going for generating the password trying every single password we can make and take a unique one out for use
    for i in range(From,To):
        # Starting the `product` module which is the main element of the program
        for j in product(chars, repeat=i):
            # Putting the generated word in the container(variable)
            word = "".join(j)

            # Checking if the password has already been used and added to the main database
            if word not in lines_set:
                # Adding to the database and returning the unique password
                with open(db, 'a') as p: # Open in append mode so we just write one new line
                    p.write(word + '\n')
                return word
2q5ifsrm

2q5ifsrm2#

这是输出的样子:

Type 1 to start generating, or type 0 to close the program:
1
agGM
Here's your unique password: agGM

只需要0.001ms!!!非常快,非常酷!!!a BIIIIGGGG thx to @slothrop!
我稍微清理了一下主代码:

from Generator import Generator
import os
import sys

while True:
    os.system('cls')
    inp = input("Type 1 to start generating, or type 0 to close the program:\n")
    if inp.isdigit():
        if inp == '1':
            break
        elif inp == '0':
            sys.exit()
gen = Generator(4, 10, "MainDB", '1', 1)
db = open("MainDB1.txt")
lines = set(db.readlines())
pwd = ''
for x in gen:
    print(x)
    if x not in lines:
        pwd = x
        break
print("Here's your unique password: "+pwd)

函数文件:

from string import *
from itertools import product

def Generator(From, To, Fname, cn, Base):
    db = 'MainDB1.txt'
    p = open(db, '+r')
    lines = []
    mainDB = open('MainDB1.txt', '+r')
    for x in mainDB.readlines():
        lines.append(x.replace('\n', ''))
    mainDB.close()
    lines = set(lines)
    Blocked = ",:?/\\|<>*"+"'"+'"'
    proBlocked = ";[]{}()+=^`"
    Blocked += proBlocked
    chars = ascii_letters + digits + punctuation
    for c in Blocked:
        chars = chars.replace(c,'')

    for i in range(From,To):
        for j in product(chars, repeat=i):
            word = "".join(j)
            if word not in lines:
                p.write(p.read() + word + '\n')
                yield word

我得说这真的是我收到的最好的问题!结果比我期待的要好得多!再次感谢@slothrop!

相关问题