Saving the output of a list to a file

Question:

I came across a project geared toward starters like myself – creating a CLI passwordcreator.

I have with the help of a few guides completed the generator and added a few of my own features, however there is one feature I can’t seem to figure out how to implement; saving the output to a file.

In the terminal the passwords shows up perfectly fine line by line, however if I try to save the output to a file it only saves the last password, and it seperates each letter by line.

My code is below, together with examples of output from both the terminal and a .txt file.

import string
import random
from os import system, name


letters = list(string.ascii_letters)
digits = list(string.digits)
special_characters = list("!@#$%^&*()£")
characters = list(string.ascii_letters + string.digits + '!@#$%^&*()£')

def clear():
    if name == 'nt':
        _ = system('CLS')

    else:
        _ = system('clear')

def generate_random_password():

    clear()

    length = int(input("Enter password length: "))
    amount = int(input('Enter amount of passwords: '))

    letters_count = int(input("Enter letter count: "))
    digits_count = int(input("Enter digits count: "))
    special_characters_count = int(input("Enter special characters count: "))

    character_count = letters_count + digits_count + special_characters_count

    if character_count > length -1:
        print("Characters total count is greater than desired password length")
        exit()

    clear()

    password = []
    print("Following passwords saved to Passwords.txt, please move the file before generating new passords, as a new generation will overwrite existing")
    print('n')

    for pwd in range(amount):
        password = []
        for c in range(digits_count):
            password.append(random.choice(digits))

        for c in range(letters_count):
            password.append(random.choice(letters))

        for c in range(special_characters_count):
            password.append(random.choice(special_characters))

        if character_count < length:
            random.shuffle(characters)
            for c in range(length - character_count):
                password.append(random.choice(characters))

                random.shuffle(password)


            if str(password) < str(length):
                return()
            else:
                print("".join(password))


            with open('Passowrds.txt', 'w') as file:
                for line in ("".join(password)):
                    file.write(line)
                    file.write('n')

            #file = open('Passwords.txt', 'w')
            #str1 = repr(password)
            #file.write('n' + str1 + 'n')
            #file.close
            #f = open('Passwords.txt', 'r')
            #if f .mode == 'r':
            #    contents=f.read

generate_random_password()

This is what the output from the terminal looks like:

Following passwords saved to Passwords.txt, please move the file
before generating new passords, as a new generation will overwrite
existing

gtBVA3QDcUohDc£TfX(zVt*24
KD8PnMD£)25hvHh#3xj79$qZI
Dx^*2£srcLvRx5g3B3(nq0H&9
&r6^3MEsaV1RuDHzxq*(h3nO)

However what is saved in the .txt file looks like this:

&
r
6
^
3
M
E
s
a
V
1
R
u
D
H
z
x
q
*
(
h
3
n
O
)
Asked By: Joawn

||

Answers:

The reason why your script is saving only 1 password is because you are opening the file to be written (which clears the contents of the file) for every password you are generating.

You want to do something along the lines of:

passwords = []
for _ in range(num_passwords):
    password = ...
    passwords.append(password)

with open("password.txt", "w") as f:
    f.writelines(passwords)

Although there is nothing terrible about the way you’re using the random library, I recommend taking a look at random.sample (without replacement) or random.choices (with replacement).

Also, using shuffling your characters list isn’t adding additional randomness to your random.choice.

You don’t have to convert the strings to lists in order to run choice:

>>> import random
>>> random.choice("abc")
'b'

A fuller example:

def generate_random_password():

    clear()

    length = int(input("Enter password length: "))
    amount = int(input("Enter amount of passwords: "))

    letters_count = int(input("Enter letter count: "))
    digits_count = int(input("Enter digits count: "))
    special_characters_count = int(input("Enter special characters count: "))

    character_count = letters_count + digits_count + special_characters_count

    if character_count > length - 1:
        print("Characters total count is greater than desired password length")
        exit()

    clear()

    passwords = []
    for _ in range(amount):
        chosen_digits = random.choices(digits, k=digits_count)
        chosen_letters = random.choices(letters, k=letters_count)
        chosen_special_characters = random.choices(
            special_characters, k=special_characters_count
        )

        extra_characters_count = length - character_count
        extra_characters = random.choices(characters, k=extra_characters_count)

        password = (
            chosen_digits
            + chosen_letters
            + chosen_special_characters
            + extra_characters
        )
        random.shuffle(password)
        passwords.append("".join(password))

    with open("Passwords.txt", "w") as f:
        f.writelines(passwords)

Answered By: sihrc
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.