有缺陷的随机密码生成器(Python 3)

时间:2016-05-03 23:38:24

标签: python python-3.x password-generator

我开始学习Python并开始尝试示例代码块。我编辑了几次,在我做的最后一次编辑中,我添加了一个可选的随机密码生成器。然后我决定将密码生成器放入单独的文档中更有意义,因此我复制了必要的代码并创建了一个新文档。但是,在编辑之后,我无法在密码中生成偶数位数。

Pastebin

Copy of Faulty Code (Pastebin)

import math
import random
alpha = ['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']
print('Would you like a random password suggestion generator', 'Yes or No')
permissionRandomGenerator = input().lower()
print('How long do you want your password?')
lengthRandomGenerator = int(input())
if permissionRandomGenerator == 'yes':
    def randInt():
        return math.floor(random.random()*10)
    def randChar():
        return alpha[math.floor(random.random()*27)]
    randPasswordList = []
    listInsert = 0
    def changeCase(f):
        g = round(random.random())
        if g == 0:
            return f.lower()
        elif g == 1:
            return f.upper()
    while listInsert < lengthRandomGenerator:
        randPasswordList.insert(listInsert, randInt())
        listInsert = listInsert + 1
        if listInsert >= lengthRandomGenerator:
            break
        randPasswordList.insert(listInsert, randChar())
        randPasswordList[listInsert] = changeCase(randPasswordList[listInsert])
        listInsert = listInsert + 1
        continue
    listInsert = 0
    printList = 0
    if lengthRandomGenerator <= 0:
        print('It has to be longer than that')
    elif lengthRandomGenerator >= 25:
        print('I can\'t generate a password that long')
    elif math.isnan(lengthRandomGenerator):
        print('error: not valid data type')
    else:
        while printList < (len(randPasswordList)-1):
            printItem = randPasswordList[printList]
            print(printItem)
            printList = printList + 1
    printList = 0
    randPasswordList = []
elif permissionRandomGenerator == 'no':
    print('Too bad...')
else:
    print('You had to answer Yes or No')

3 个答案:

答案 0 :(得分:1)

我重构了你的程序,并摆脱了很多不必要的步骤和不一致。在这里它是完整的,然后我将解释每个部分:

import random
import string
import sys

possible_chars = string.ascii_letters + string.digits + string.punctuation

def nextchar(chars):
    return random.choice(chars)

yes_or_no = input("""
Would you like a random password suggestion generated?
Type Yes to continue: """).lower()

if yes_or_no == 'yes':
    try:
        pwd_len = int(input('How long do you want your password? '))
    except ValueError:
        sys.exit("You need to enter an integer. Please start the program over.")

    if 0 < pwd_len < 26:
        new_pwd = ""
        for _ in range(pwd_len):
            new_pwd += nextchar(possible_chars)
        print("Your new password is:\n" + new_pwd)

    else:
        print("I can only generate passwords between 1 and 25 characters long.")

else:
    print("Well then, why did you run me?")

Python不只是语法和builtin functions,它还是standard library或stdlib。您将一直使用stdlib的模块,所以当您认为自己正在使用它时,阅读文档!您将会这样做了解模块,它的用途是什么,它的一些历史和变化(例如添加某个功能的版本),以及其中包含的所有类,函数和属性。确保你阅读了整个事情(它们都不是那个长),并试图至少了解每件事情的基本概念。这样,例如在这种情况下,您就可以为工作选择最佳功能。我在业余时间喜欢做的一件事就是选择一个随机模块并阅读文档,只是为了学习。它们通常编写得相当好,而且通常非常具有包容性。习惯了Monty Python的引用,它们无处不在。

import random
import string
import sys

进口是第一位的,而且应该几乎总是只在顶部。我喜欢按字母顺序放置我的,stdlib在顶部,然后是空白行,然后是第三方模块,包括下面的自写模块。在导入之后放一两行空白。有一点要记住,我在评论中提到:可读性很重要。代码不仅要由机器读取,还要由人们读取。必要时评论。对空格很慷慨(还要记住,在Python中,空格在语法上也很重要,因此它会强制你缩进)以分离相关的代码,函数,类,块等。我高度推荐阅读,重读和花时间思考Python风格指南PEP-8。它的建议不是绝对,但许多强制执行编码标准的项目依赖于它。尽可能多地遵循它。如果一行有83个字符,请不要出汗,但要注意你正在做的事情。

我在阅读文档时做出如此重大的原因有以下几点:

possible_chars = string.ascii_letters + string.digits + string.punctuation

def nextchar(chars):
    return random.choice(chars)

他们摆脱了大约一半的代码。 string包含一堆用于处理字符串的预定义常量。我选择的三个都应该是有效的密码字符。如果您使用的是不会使用标点符号的系统,请将其删除。请注意,possible_chars是一个字符串 - 类似于元组,列表和字符串,字符串是可迭代的,因此您不需要为每个可能的字符创建单独的列表。

接下来是功能 - 它会替换您的randInt()randChar()changeCase()函数,以及一堆内联代码,这些代码很奇怪,可以说实话。我喜欢你提出的方法来决定一个字母是大写还是小写,但是当你有random.choice()和{时,其余的只是方式太多的努力来自上面的{1}}常数。

string

您可能没有意识到,但在获取用户yes_or_no = input(""" Would you like a random password suggestion generated? Type Yes to continue: """).lower() 之前,您不需要print()描述字符串 - 只需将字符串作为单个参数传递给input()而且你会得到同样的效果。我还使用了triple-quoted input()(也可以使用""")字符串文字,它与更常见的单'''和双引'字符串不同文字,因为其中包含的任何换行符或标签都不需要转义。现在的好处是你可以写几行文字,当你"时,它会出现几行。

print()

我在下一部分使用了try/except块。如果用户在输入提示符处输入非整数,则 try: pwd_len = int(input('How long do you want your password? ')) except ValueError: sys.exit("You need to enter an integer. Please start the program over.") 函数将失败并显示ValueError。我选择了最简单的处理方法:如果出现错误,请打印一条消息然后退出。如果出现错误,你可以使程序重新询问输入,但我认为这超出了本练习的范围。

int()

这是所有行动发生的地方。使用 if 0 < pwd_len < 26: new_pwd = "" for _ in range(pwd_len): new_pwd += nextchar(possible_chars) print("Your new password is:\n" + new_pwd) else: print("I can only generate passwords between 1 and 25 characters long.") 块,我们测试所需的密码长度,如果它在1到25之间(任意上限),我们生成密码。这是通过if/else循环和range()函数完成的(阅读文档以了解其工作原理)。您会注意到我在for循环中使用了常见的Python习惯用法:因为我实际上需要 for生成的数字,我{ {3}}使用下划线range()字符代替变量。最后,_语句处理替代方案 - else为0或更小,或者26或更大。

pwd_len

我们在计划结束时!此else: print("Well then, why did you run me?") else语句配对 - 用户在输入提示符处输入了“是”以外的内容。

希望这有助于您更多地了解Python的工作原理以及如何有效地使用它进行编程。如果你觉得你花了太多时间来实现你认为应该更容易的东西,你可能是对的。 Python的许多优点之一是其包含的电池和#34;哲学 - 你可以用stdlib做很多事情。

答案 1 :(得分:0)

我做了一些小编辑,我的代码现在似乎正在运行。这是完成的产品(我发表评论以显示代码的作用,并标记编辑。):

import math
import random                                 #Import necessary modules
alpha = ['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']  #List with alphabet
print('Would you like a random password suggestion generator', 'Yes or No')  #Prints the question for permission
permissionRandomGenerator = input().lower()   #Stores the answer of the above question in lower case
if permissionRandomGenerator == 'yes':        #Generates a password if the answer of the first question is 'yes'
print('How long do you want your password?')  #Asks for length
lengthRandomGenerator = int(input())          #Stores length as an integer
    def randInt():                            #Creates a random integer
        return math.floor(random.random()*10)
    def randChar():                          #Selects a random string from the list with the alphabet
        return alpha[math.floor(random.random()*27) - 1]
    randPasswordList = []                    #Creates a list to store the password
    listInsert = 0                           #Creates a list index variable
    def changeCase(f):                       #Defines a function to randomly change the case of letters before adding them to the list randPasswordList
        g = round(random.random())
        if g == 0:
            return f.lower()
        elif g == 1:
            return f.upper()
    while listInsert < lengthRandomGenerator + 1:  #Creates a random password and inserts it into randPasswordList  (I added `+ 1` here)
        randPasswordList.insert(listInsert, randInt())
        listInsert = listInsert + 1
        if listInsert >= lengthRandomGenerator:
            break
        randPasswordList.insert(listInsert, randChar())
        randPasswordList[listInsert] = changeCase(randPasswordList[listInsert])    #Calls the changeCase function whenever it inserts a letter
        listInsert = listInsert + 1
        continue
    listInsert = 0
    printList = 0
    if lengthRandomGenerator <= 0:           #If the length it 0 or less (for example, negatives) the password will not generate (I need to fix this a little bit.  Currently the code attempts to create a password beforehand)
        print('It has to be longer than that')
    elif lengthRandomGenerator >= 25:
        print('I can\'t generate a password that long')
    elif math.isnan(lengthRandomGenerator):  #Currently this doesn't do anything, it needs to be moved farther forward
        print('error: not valid data type')
    else:
        while printList < (len(randPasswordList)-1):    #Prints the list item by item
            printItem = randPasswordList[printList]
            print(printItem)
            printList = printList + 1
    printList = 0                             #Resets the variables
    randPasswordList = []
elif permissionRandomGenerator == 'no':
    print('Too bad...')
else:
    print('You had to answer Yes or No')

注意:我将此代码纯粹用于实验并更好地学习Python的基本方面。这段代码没有经过优化,也没有像我能做的那样随机。

P.S。对不起,如果评论不完整,我仍然在学习这门语言。

答案 2 :(得分:0)

我不知道为什么你为这个简单的问题做了复杂的事情,你可以使用string对象提供的常量,我宁愿让以下程序生成随机密码

import random, sys, string

def pgen(length=8):
    if length < 8:
        length = 8 
    keys = list(string.printable[:-6])
    random.shuffle(keys)
    return ''.join(keys)[:length]


if __name__ == '__main__':
    try:
        print( pgen(int(sys.argv[1])))
    except Exception as e:
        print("Provide length of password \n passwordgen.py <length_of_password>")

输出

magautam@nix1947:/tmp$ python passwordgen.py 12
HNLxi!{.qe=b

magautam@nix1947:/tmp$ python passwordgen.py 45
}w5u?+C=e[DfI.n'*1G(m{r0FH|UBKz/@kL>;Sh`tEW8-