使用嵌套函数生成随机字符串的函数给我带来了麻烦
Function to generate random string with nested function is giving me trouble
我要先说我对此很陌生,不要评判哈哈。
我写的脚本是从不同的字符串中随机生成一个密码并将它们随机化。我已经成功完成,但知道我想为该脚本构建一个 GUI,函数和 tkinter 的实现给我带来了麻烦。我有两个函数:一个 (add2all) 应该检查变量是否为真,如果为真,则将其添加到字符串“all”,我稍后将使用我的第二个函数进行随机化。我确信我如何从 Checkbuttons 中获取值(用于让用户输入他们想要在密码中使用什么样的字符)以及如何将它们添加到字符串中存在问题。如果用户键入一个 int,我的第二个函数 (pwdgen) 应该从输入框中获取输入长度,然后调用 add2all 函数来查看用户想要的字符。 add2all 应该生成一个包含所有已定义为 true 的字符的字符串,以便 pwdgen 可以将它们随机化为给定的长度。我还有一个应该启动该过程的按钮。它调用 pwdgen,然后调用 add2all,最后,变量密码应该有一个随机字符串,我可以将其显示到输入框。
TL;DR:我之前编写的一个非常简单的脚本的功能和 tkinter 实现根本不起作用。
import random
from tkinter import *
from tkinter import ttk
root = Tk()
upper, lower, nums, syms = False, False, False, False
uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
lowercase = "abcdefghijklmnopqrstuvwxyz"
digits = "1234567890"
symbols = "!§$%&?*+#~-;()/"
all = StringVar()
CheckBool1 = IntVar()
CheckBool2 = IntVar()
CheckBool3 = IntVar()
CheckBool4 = IntVar()
pwlength = IntVar()
#function that checks if a CheckButton input (which characters are wanted in password)
#is true, if true adds the corresponding character string to the all string
def add2all():
if CheckBool1:
upper = True
if CheckBool2:
lower = True
if CheckBool3:
nums = True
if CheckBool4:
syms = True
if upper:
all += uppercase
if lower:
all += lowercase
if nums:
all += digits
if syms:
all += symbols
#function that gets password length from user, then calls add2all, then gives var password
#the string of all randomized with specified length and then puts it into entry box pwdoupt
def pwdgen():
pwdoutpt.delete(0, END)
v = amt.get()
v = pwlength
add2all()
password = "".join(random.choices(all, k=pwlength))
pwdoutpt.insert(0, password)
greet = Label(root, text="Welcome to the interactive password generator!", height=3)
pwdoutpt = Entry(root, width=30)
generate = Button(root, text="Generate", command = lambda: pwdgen())
#inits all the labels and checkbuttons for my gui
chck_1 = Checkbutton(root, width = 5, var = CheckBool1)
chck_2 = Checkbutton(root, width = 5, var = CheckBool2)
chck_3 = Checkbutton(root, width = 5, var = CheckBool3)
chck_4 = Checkbutton(root, width = 5, var = CheckBool4)
lbl_1 = Label(root, text="Capital Letters")
lbl_2 = Label(root, text="Lowercase Letters")
lbl_3 = Label(root, text="Digits")
lbl_4 = Label(root, text="Symbols")
amt = Entry(root, width = 5)
amtlbl = Label(root, text="Num of characters in pwd.")
sep = ttk.Separator(root, orient="horizontal")
greet.grid(column=0, row=0, columnspan=4, pady=3)
pwdoutpt.grid(column=0, row=7, columnspan=4, padx=30, sticky=W)
amt.grid(column=0, row=1, sticky=W)
amtlbl.grid(column=1, row=1, columnspan=1, sticky=E)
chck_1.grid(column=0, row=2, sticky=E)
chck_2.grid(column=0, row=3, sticky=E)
chck_3.grid(column=0, row=4, sticky=E)
chck_4.grid(column=0, row=5, sticky=E)
lbl_1.grid(column=1, row=2, columnspan=1, sticky=W)
lbl_2.grid(column=1, row=3, columnspan=1, sticky=W)
lbl_3.grid(column=1, row=4, columnspan=1, sticky=W)
lbl_4.grid(column=1, row=5, columnspan=1, sticky=W)
sep.grid(column=0, columnspan=10, row=6, sticky=EW)
generate.grid(column=2, row=7)
root.mainloop()
首先,不要使用 all
作为 StringVar
的变量名;这是一个内置的 python 函数。不要使用通配符导入 (from <module> import *
),这是一个坏习惯,不符合 PEP8。相反,使用 import tkinter as tk
.
你需要阅读how to use一篇StringVar
;它不是一个字符串,你不能像一个一样添加它。在此代码中使用 StringVar
的一个很好的应用是显示生成的密码。如果将 StringVar
绑定到 pwdoutpt
Entry
,更新 StringVar
将自动显示更新后的字符串。
您说您的密码生成器已经正常工作。为什么不稍微调整一下密码生成器函数,使其将长度和字符类型作为输入,并 returns 随机生成密码?您目前正在尝试将密码生成功能集成到 GUI 代码中,这是一个坏主意,因为它会很快变得混乱。
考虑到以上所有因素,这里是您的代码的有效修改版本:
import random
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
# Your password generating function
def pwdgen(password_length, chars_allowed):
chars = [
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"abcdefghijklmnopqrstuvwxyz",
"1234567890",
"!§$%&?*+#~-;()/"
]
valid_chars = [x for i, x in enumerate(chars) if chars_allowed[i] == True]
valid_chars = "".join(valid_chars)
password = "".join(random.choices(valid_chars, k=password_length))
return password
# Set up tkinter window
root = tk.Tk()
root.title("Password generator")
# Vars for checkbuttons and password entry
CheckBool1 = tk.IntVar()
CheckBool2 = tk.IntVar()
CheckBool3 = tk.IntVar()
CheckBool4 = tk.IntVar()
password = tk.StringVar()
# Main widgets
greet = tk.Label(root, text="Welcome to the interactive password generator!", height=3)
chck_1 = tk.Checkbutton(root, width = 5, var = CheckBool1)
chck_2 = tk.Checkbutton(root, width = 5, var = CheckBool2)
chck_3 = tk.Checkbutton(root, width = 5, var = CheckBool3)
chck_4 = tk.Checkbutton(root, width = 5, var = CheckBool4)
lbl_1 = tk.Label(root, text="Capital Letters")
lbl_2 = tk.Label(root, text="Lowercase Letters")
lbl_3 = tk.Label(root, text="Digits")
lbl_4 = tk.Label(root, text="Symbols")
amt = tk.Entry(root, width = 5)
amtlbl = tk.Label(root, text="Num of characters in pwd.")
sep = ttk.Separator(root, orient="horizontal")
# Password output
pwdoutpt = tk.Entry(root, width=30, textvariable=password, state="readonly")
# Generate password function and button
def insert_password():
try:
password_length = int(amt.get())
chars_allowed = [CheckBool1.get(), CheckBool2.get(), CheckBool3.get(), CheckBool4.get()]
password.set(pwdgen(password_length, chars_allowed))
except ValueError:
messagebox.showerror("Error", "Invalid password length")
except IndexError:
messagebox.showerror("Error", "No character type selected")
generate = tk.Button(root, text="Generate", command = insert_password)
# Gridding widgets
greet.grid(column=0, row=0, columnspan=4, pady=3)
pwdoutpt.grid(column=0, row=7, columnspan=4, padx=30, sticky=tk.W)
amt.grid(column=0, row=1, sticky=tk.W)
amtlbl.grid(column=1, row=1, columnspan=1, sticky=tk.E)
chck_1.grid(column=0, row=2, sticky=tk.E)
chck_2.grid(column=0, row=3, sticky=tk.E)
chck_3.grid(column=0, row=4, sticky=tk.E)
chck_4.grid(column=0, row=5, sticky=tk.E)
lbl_1.grid(column=1, row=2, columnspan=1, sticky=tk.W)
lbl_2.grid(column=1, row=3, columnspan=1, sticky=tk.W)
lbl_3.grid(column=1, row=4, columnspan=1, sticky=tk.W)
lbl_4.grid(column=1, row=5, columnspan=1, sticky=tk.W)
sep.grid(column=0, columnspan=10, row=6, sticky=tk.EW)
generate.grid(column=2, row=7)
root.mainloop()
关于代码的一些进一步说明:
- 函数
insert_password
使用 try except 在生成密码之前测试输入是否正确。
pwdoutpt
有state="readonly"
这样用户不能修改生成的密码但仍然可以复制
我要先说我对此很陌生,不要评判哈哈。 我写的脚本是从不同的字符串中随机生成一个密码并将它们随机化。我已经成功完成,但知道我想为该脚本构建一个 GUI,函数和 tkinter 的实现给我带来了麻烦。我有两个函数:一个 (add2all) 应该检查变量是否为真,如果为真,则将其添加到字符串“all”,我稍后将使用我的第二个函数进行随机化。我确信我如何从 Checkbuttons 中获取值(用于让用户输入他们想要在密码中使用什么样的字符)以及如何将它们添加到字符串中存在问题。如果用户键入一个 int,我的第二个函数 (pwdgen) 应该从输入框中获取输入长度,然后调用 add2all 函数来查看用户想要的字符。 add2all 应该生成一个包含所有已定义为 true 的字符的字符串,以便 pwdgen 可以将它们随机化为给定的长度。我还有一个应该启动该过程的按钮。它调用 pwdgen,然后调用 add2all,最后,变量密码应该有一个随机字符串,我可以将其显示到输入框。
TL;DR:我之前编写的一个非常简单的脚本的功能和 tkinter 实现根本不起作用。
import random
from tkinter import *
from tkinter import ttk
root = Tk()
upper, lower, nums, syms = False, False, False, False
uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
lowercase = "abcdefghijklmnopqrstuvwxyz"
digits = "1234567890"
symbols = "!§$%&?*+#~-;()/"
all = StringVar()
CheckBool1 = IntVar()
CheckBool2 = IntVar()
CheckBool3 = IntVar()
CheckBool4 = IntVar()
pwlength = IntVar()
#function that checks if a CheckButton input (which characters are wanted in password)
#is true, if true adds the corresponding character string to the all string
def add2all():
if CheckBool1:
upper = True
if CheckBool2:
lower = True
if CheckBool3:
nums = True
if CheckBool4:
syms = True
if upper:
all += uppercase
if lower:
all += lowercase
if nums:
all += digits
if syms:
all += symbols
#function that gets password length from user, then calls add2all, then gives var password
#the string of all randomized with specified length and then puts it into entry box pwdoupt
def pwdgen():
pwdoutpt.delete(0, END)
v = amt.get()
v = pwlength
add2all()
password = "".join(random.choices(all, k=pwlength))
pwdoutpt.insert(0, password)
greet = Label(root, text="Welcome to the interactive password generator!", height=3)
pwdoutpt = Entry(root, width=30)
generate = Button(root, text="Generate", command = lambda: pwdgen())
#inits all the labels and checkbuttons for my gui
chck_1 = Checkbutton(root, width = 5, var = CheckBool1)
chck_2 = Checkbutton(root, width = 5, var = CheckBool2)
chck_3 = Checkbutton(root, width = 5, var = CheckBool3)
chck_4 = Checkbutton(root, width = 5, var = CheckBool4)
lbl_1 = Label(root, text="Capital Letters")
lbl_2 = Label(root, text="Lowercase Letters")
lbl_3 = Label(root, text="Digits")
lbl_4 = Label(root, text="Symbols")
amt = Entry(root, width = 5)
amtlbl = Label(root, text="Num of characters in pwd.")
sep = ttk.Separator(root, orient="horizontal")
greet.grid(column=0, row=0, columnspan=4, pady=3)
pwdoutpt.grid(column=0, row=7, columnspan=4, padx=30, sticky=W)
amt.grid(column=0, row=1, sticky=W)
amtlbl.grid(column=1, row=1, columnspan=1, sticky=E)
chck_1.grid(column=0, row=2, sticky=E)
chck_2.grid(column=0, row=3, sticky=E)
chck_3.grid(column=0, row=4, sticky=E)
chck_4.grid(column=0, row=5, sticky=E)
lbl_1.grid(column=1, row=2, columnspan=1, sticky=W)
lbl_2.grid(column=1, row=3, columnspan=1, sticky=W)
lbl_3.grid(column=1, row=4, columnspan=1, sticky=W)
lbl_4.grid(column=1, row=5, columnspan=1, sticky=W)
sep.grid(column=0, columnspan=10, row=6, sticky=EW)
generate.grid(column=2, row=7)
root.mainloop()
首先,不要使用 all
作为 StringVar
的变量名;这是一个内置的 python 函数。不要使用通配符导入 (from <module> import *
),这是一个坏习惯,不符合 PEP8。相反,使用 import tkinter as tk
.
你需要阅读how to use一篇StringVar
;它不是一个字符串,你不能像一个一样添加它。在此代码中使用 StringVar
的一个很好的应用是显示生成的密码。如果将 StringVar
绑定到 pwdoutpt
Entry
,更新 StringVar
将自动显示更新后的字符串。
您说您的密码生成器已经正常工作。为什么不稍微调整一下密码生成器函数,使其将长度和字符类型作为输入,并 returns 随机生成密码?您目前正在尝试将密码生成功能集成到 GUI 代码中,这是一个坏主意,因为它会很快变得混乱。
考虑到以上所有因素,这里是您的代码的有效修改版本:
import random
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
# Your password generating function
def pwdgen(password_length, chars_allowed):
chars = [
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"abcdefghijklmnopqrstuvwxyz",
"1234567890",
"!§$%&?*+#~-;()/"
]
valid_chars = [x for i, x in enumerate(chars) if chars_allowed[i] == True]
valid_chars = "".join(valid_chars)
password = "".join(random.choices(valid_chars, k=password_length))
return password
# Set up tkinter window
root = tk.Tk()
root.title("Password generator")
# Vars for checkbuttons and password entry
CheckBool1 = tk.IntVar()
CheckBool2 = tk.IntVar()
CheckBool3 = tk.IntVar()
CheckBool4 = tk.IntVar()
password = tk.StringVar()
# Main widgets
greet = tk.Label(root, text="Welcome to the interactive password generator!", height=3)
chck_1 = tk.Checkbutton(root, width = 5, var = CheckBool1)
chck_2 = tk.Checkbutton(root, width = 5, var = CheckBool2)
chck_3 = tk.Checkbutton(root, width = 5, var = CheckBool3)
chck_4 = tk.Checkbutton(root, width = 5, var = CheckBool4)
lbl_1 = tk.Label(root, text="Capital Letters")
lbl_2 = tk.Label(root, text="Lowercase Letters")
lbl_3 = tk.Label(root, text="Digits")
lbl_4 = tk.Label(root, text="Symbols")
amt = tk.Entry(root, width = 5)
amtlbl = tk.Label(root, text="Num of characters in pwd.")
sep = ttk.Separator(root, orient="horizontal")
# Password output
pwdoutpt = tk.Entry(root, width=30, textvariable=password, state="readonly")
# Generate password function and button
def insert_password():
try:
password_length = int(amt.get())
chars_allowed = [CheckBool1.get(), CheckBool2.get(), CheckBool3.get(), CheckBool4.get()]
password.set(pwdgen(password_length, chars_allowed))
except ValueError:
messagebox.showerror("Error", "Invalid password length")
except IndexError:
messagebox.showerror("Error", "No character type selected")
generate = tk.Button(root, text="Generate", command = insert_password)
# Gridding widgets
greet.grid(column=0, row=0, columnspan=4, pady=3)
pwdoutpt.grid(column=0, row=7, columnspan=4, padx=30, sticky=tk.W)
amt.grid(column=0, row=1, sticky=tk.W)
amtlbl.grid(column=1, row=1, columnspan=1, sticky=tk.E)
chck_1.grid(column=0, row=2, sticky=tk.E)
chck_2.grid(column=0, row=3, sticky=tk.E)
chck_3.grid(column=0, row=4, sticky=tk.E)
chck_4.grid(column=0, row=5, sticky=tk.E)
lbl_1.grid(column=1, row=2, columnspan=1, sticky=tk.W)
lbl_2.grid(column=1, row=3, columnspan=1, sticky=tk.W)
lbl_3.grid(column=1, row=4, columnspan=1, sticky=tk.W)
lbl_4.grid(column=1, row=5, columnspan=1, sticky=tk.W)
sep.grid(column=0, columnspan=10, row=6, sticky=tk.EW)
generate.grid(column=2, row=7)
root.mainloop()
关于代码的一些进一步说明:
- 函数
insert_password
使用 try except 在生成密码之前测试输入是否正确。 pwdoutpt
有state="readonly"
这样用户不能修改生成的密码但仍然可以复制