Primo generatore di password in Python

Sep 10 2020

Questo è il mio primo progetto che utilizza Python. Ho creato un semplice generatore di password che controlla l'input dell'utente. Come posso migliorarlo?

import random
def password_generator():
    password = []
    letters = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
               "v", "w", "x", "y", "z"]
    password_length = 0
    password_numbers = []
    password_letters = []
    # Input the length of the password
    while True:
        password_length_input = input("Choose the length of your password with numbers between 6 and 15:\n")
        if not password_length_input.isnumeric():
            print(f"{password_length_input} is not a number, try again:")
            continue
        else:
            password_length = int(password_length_input)
            print(f"Password length: {password_length}")
        if 6 <= password_length <= 15:
            break
        else:
            print("The password must be between 6 and 15 characters, try again:")
            continue
    # Input the amount of numbers in password
    while True:
        password_numbers_input = \
            input(f"Choose the amount of numbers you want in your password, max {password_length}\n")
        if not password_numbers_input.isnumeric():
            print(f"{password_numbers_input} is not a number try again")
            continue
        elif int(password_numbers_input) > password_length:
            password_numbers = 0
            print(f"The value is too high, choose maximum {password_length} numbers")
            continue
        else:
            password_numbers = int(password_numbers_input)
            print(f"Password numbers: {password_numbers}")
            for number in range(0,password_numbers):
                password.append(random.randrange(0,9))
            break
    # Check for numbers and letters in password
    while True:
        if password_numbers == password_length:
            print(f"The password will be only {password_numbers} numbers, no letters.")
            break
        else:
            password_letters = password_length - password_numbers
            print(f"""Your password will be {password_length} characters with {password_numbers} numbers and {password_letters} letters.""")
            for letter in range(0,password_letters):
                password.append(random.choice(letters))
            break
    random.shuffle(password)
    password_string = ''.join([str(item) for item in password])
    print(f"Your password is:\n{password_string}")

password_generator()

Esempio di utilizzo:

Choose the length of your password with numbers between 6 and 15:
Password length: 8
Choose the amount of numbers you want in your password, max 8
Password numbers: 2
Your password will be 8 characters with 2 numbers and 6 letters.
Your password is:
pzc11bmf

Risposte

9 benrg Sep 10 2020 at 22:06
letters = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u",`
           "v", "w", "x", "y", "z"]

Questo metodo di scrittura dell'alfabeto è molto soggetto a errori. Vorrei importare stringe utilizzare string.ascii_lowercaseal posto di letters. Se vuoi generare il tuo intervallo di lettere per qualsiasi motivo, ti scrivo

letters = [chr(n) for n in range(ord('a'), ord('z') + 1)]

poiché allora non c'è pericolo di omettere o duplicare una lettera.


password_length = 0
password_numbers = []
password_letters = []

Questi valori predefiniti non vengono mai utilizzati. I valori predefiniti per password_numberse password_lettersnon hanno senso poiché quelle variabili contengono numeri. Eliminerei tutte e tre le righe.


if not password_length_input.isnumeric():
    print(f"{password_length_input} is not a number, try again:")
    continue
else:
    password_length = int(password_length_input)
    print(f"Password length: {password_length}")

Vorrei invece scrivere

try:
    password_length = int(password_length_input)
except ValueError:
    print(f"{password_length_input} is not a number, try again:")
    continue
print(f"Password length: {password_length}")

while True:
    if password_numbers == password_length:
        ...
        break
    else:
        ...
        break

Non ha senso avere un whileloop qui poiché ne esci sempre alla prima iterazione.


range(0,password_numbers)

Puoi solo scrivere range(password_numbers).


password.append(random.randrange(0,9))

Questo aggiungerà una cifra da 0 a 8 inclusi, mai 9. Se vuoi tutte e dieci le cifre dovresti scrivere random.randrange(10). O, forse meglio, usa random.choice(string.digits).


password_string = ''.join([str(item) for item in password])

Se usi, string.digitsogni elemento di passwordsarà un personaggio, quindi puoi semplificarlo password_string = ''.join(password).

6 Anonymous Sep 10 2020 at 20:31

Un modo più semplice per generare una stringa casuale:

import random
import string

    def get_random_string(length):
        letters = string.ascii_lowercase
        result_str = ''.join(random.choice(letters) for i in range(length))
        print("Random string of length", length, "is:", result_str)
    
    get_random_string(8)
    get_random_string(8)
    get_random_string(6)

preso in prestito da qui , e ci sono altri esempi.

Ora se hai requisiti specifici come un numero minimo di cifre, puoi modificare la formula o generare due elenchi e unirli mescolando i valori.

C'è un esempio nel link che ho citato sopra: "Genera una stringa alfanumerica casuale con un conteggio fisso di lettere e cifre" => unendo due liste di comprensione.

Il modo in cui lo fai è procedurale ma non pitonico. È un po 'reinventare la ruota.

Per lo meno, il tuo elenco di caratteri consentiti dovrebbe essere simile a questo:

letters = "abcdefghijklmnopqrstuvwxyz"

Quindi scegli una lettera casuale, ad esempio letters[3]restituirà "d" poiché l'elenco è basato su 0 e Python tratta le stringhe come sequenze di caratteri. Usando lo shuffle come stai già facendo, puoi scrivere un codice più conciso.

3 K.Oleksy Sep 10 2020 at 19:19

Primo

Suggerisco di creare metodi separati per ogni ciclo while.

Secondo

Il ciclo "while True" non è una buona pratica, credo. Invece, usa la condizione.

Terzo

Suggerisco di creare la classe PasswordGenerator che conterrà il tuo codice. Ti aiuterà ad espandere il tuo codice in futuro.

Struttura di base per il tuo progetto

 class PasswordGenerator():
     
    check_declared_password_length():
        ...
        
    check_amount_of_password_numbers():
        ...
    *
    *
    *

Per la fine ricordati di creare funzioni con una responsabilità. Dopodiché, puoi scrivere unit test per ciascuno di essi e sarà più facile.