用python写了一个随机密码生成器,分享一下
本帖最后由 bing52 于 2023-12-2 18:09 编辑编程语言: python3.11
图形模块: PySimpleGUI
实现思路:
1. 密码组成部分:大写字母,小写字母,数字,特殊字符
2. 根据用户选择的组成部分和密码长度
2.1: 计算组成部分个数n, 将密码长度随机分成n份生成列表m
2.2: 根据遍历并随机获取每个组成部分的数据,每个组成部分的长度m
2.3: 打乱顺序,组装成字符串输出
成品:
关键代码:
def getRandom(leng: int, typnum: int):
num_list = []
# 如果密码长度和密码复杂度一致,就默认设置为1
if leng == typnum:
return
for i in range(typnum, 0, -1):
num_list.append(random.randint(1, leng - sum(num_list) - i))
num_list += leng - sum(num_list)
num_list.sort(reverse=True)
return num_list
def randmima(key: list,
leng: int,
special: Optional = '~!@#$%^&*()-_=+?><.,'):
# 字典项
atomDict = {
'lowers': string.ascii_lowercase,
'uppers': string.ascii_uppercase,
'numbers': string.digits,
'sym': special if special else string.punctuation
}
# 获取每个原子项分的长度数组
if len(key) > leng:
raise KeyError("密码长度不能小于复杂度个数")
numList = getRandom(leng, len(key))
seclist = []
for index, value in enumerate(numList):
seclist += random.choices(atomDict], k=value)
# 重新排序
random.shuffle(seclist)
return "".join(seclist)
def batchPwd(optionDict: dict) -> str:
atomList = ['lowers', 'uppers', 'numbers', 'sym']
secList = []
atom = [
key for key, value in optionDict.items() if key in atomList and value
]
# 判断原子数据是否为空
if not atom:
return "至少选择一项"
random.shuffle(atom)
for _ in range(int(optionDict['pwdCount'])):
secList.append(
randmima(atom,
int(optionDict['pwdlength']),
special=optionDict['spclistr']))
return "\n".join(secList)
def main():
# 图形界面
pdict = {
'uppers': True,
'lowers': True,
'numbers': True,
'sym': True,
'pwdlength': 12,
'pwdCount': 5,
'spclistr': None
}
sg.theme("Dark Brown")
optional = {'font': "MicrosoftYaHei 14", "margins": (10, 10)}
config_option_spcil1 = [
sg.Checkbox("大写字母", default=True, key="uppers", enable_events=True),
sg.Checkbox("小写字母", default=True, key="lowers", enable_events=True),
sg.Checkbox("数字", default=True, key="numbers", enable_events=True)
]
config_spcil2_option = [
sg.Checkbox('', default=True, key="sym", enable_events=True),
sg.Input('.,$#@!^&*-_=+:;?',
size=(25, 1),
key="spclistr",
disabled=False,
enable_events=True)
]
config_option = [
sg.Text("密码组成: "),
sg.Column()
]
config_resgen_btn =
btn_column = , justification="right")]
pwd_length_option = [
sg.Text("密码长度: "),
sg.Slider(range=(4, 50),
default_value=pdict['pwdlength'],
orientation='h',
enable_events=True,
disable_number_display=True,
size=(28, 15),
key='pwdlength'),
sg.Text(pdict['pwdlength'], key='-PWDLEN-')
]
config_count = [
sg.Text("生成个数: "),
sg.Slider(range=(1, 100),
default_value=pdict['pwdCount'],
orientation='h',
enable_events=True,
disable_number_display=True,
size=(28, 15),
key='pwdCount'),
sg.Text(pdict['pwdCount'], key='-count-')
]
result_option = [
sg.Multiline(default_text=batchPwd(pdict),
autoscroll=True,
horizontal_scroll=True,
disabled=True,
size=(50, 15),
key="-pwdResult-")
]
layout = [[
sg.Frame("参数设置",
,
size=(450, 200))
], , size=(450, 300))]]
window = sg.Window("随机密码生成器", layout=layout, **optional)
while True:
event, values = window.read()# type: ignore
if event == sg.WIN_CLOSED:
break
if event == 'pwdCount':
window['-count-'].update(value=str(int(values['pwdCount'])))
if event == 'pwdlength':
window['-PWDLEN-'].update(value=str(int(values['pwdlength'])))
if event == 'sym':
window['spclistr'].update(disabled=not values['sym'])
if event in [
'sym', 'numbers', 'lowers', 'uppers', 'pwdlength', 'pwdCount',
'spclistr', '-regeneration-'
]:
window['-pwdResult-'].update(value=batchPwd(values))
window.close()
if __name__ == "__main__":
main()
关键代码都在这里了,我就不搞文件了。各位如果有什么好的想法和建议可以留言 本帖最后由 bing52 于 2023-12-3 20:49 编辑
根据各位提的意见,我又修改了一版添加了自动复制的功能, 不过用listbox有个bug,就是一些特殊字符的密码显示的时候会用{}包裹,搞了半天没有搞定,不过不影响复制和粘贴, 有大佬搞定的可以告诉我一下
bug截图:
修改后的代码:
import random
import string
from typing import Optional
import PySimpleGUI as sg
import pyperclip as pc
def getRandom(leng: int, typnum: int):
num_list = []
# 如果密码长度和密码复杂度一致,就默认设置为1
if leng == typnum:
return
for i in range(typnum, 0, -1):
num_list.append(random.randint(1, leng - sum(num_list) - i))
num_list += leng - sum(num_list)
num_list.sort(reverse=True)
return num_list
def randmima(key: list,
leng: int,
special: Optional = '~!@#$%^&*()-_=+?><.,'):
# 字典项
atomDict = {
'lowers': string.ascii_lowercase,
'uppers': string.ascii_uppercase,
'numbers': string.digits,
'sym': special if special else string.punctuation
}
# 获取每个原子项分的长度数组
if len(key) > leng:
raise KeyError("密码长度不能小于复杂度个数")
numList = getRandom(leng, len(key))
seclist = []
for index, value in enumerate(numList):
seclist += random.choices(atomDict], k=value)
# 重新排序
random.shuffle(seclist)
return "".join(seclist)
def batchPwd(optionDict: dict) -> list:
atomList = ['lowers', 'uppers', 'numbers', 'sym']
secList = []
atom = [
key for key, value in optionDict.items() if key in atomList and value
]
# 判断原子数据是否为空
if not atom:
return ["至少选择一项"]
random.shuffle(atom)
for index in range(int(optionDict['pwdCount'])):
secList.append(
), special=optionDict['spclistr'])])
# return "\n".join(secList)
return secList
def main():
# 图形界面
pdict = {
'uppers': True,
'lowers': True,
'numbers': True,
'sym': True,
'pwdlength': 12,
'pwdCount': 5,
'spclistr': None
}
pwds = batchPwd(pdict)
sg.theme("Dark Brown")
optional = {'font': "MicrosoftYaHei 14", "margins": (10, 10)}
config_option_spcil1 = [
sg.Checkbox("大写字母", default=True, key="uppers", enable_events=True),
sg.Checkbox("小写字母", default=True, key="lowers", enable_events=True),
sg.Checkbox("数字", default=True, key="numbers", enable_events=True)
]
config_spcil2_option = [
sg.Checkbox('', default=True, key="sym", enable_events=True),
sg.Input('.,$#@!^&*-_=+:;?',
size=(25, 1),
key="spclistr",
disabled=False,
enable_events=True)
]
config_option = [
sg.Text("密码组成: "),
sg.Column()
]
config_resgen_btn =
btn_column = , justification="right")]
pwd_length_option = [
sg.Text("密码长度: "),
sg.Slider(range=(4, 50),
default_value=pdict['pwdlength'],
orientation='h',
enable_events=True,
disable_number_display=True,
size=(28, 15),
key='pwdlength'),
sg.Text(pdict['pwdlength'], key='-PWDLEN-')
]
config_count = [
sg.Text("生成个数: "),
sg.Slider(range=(1, 100),
default_value=pdict['pwdCount'],
orientation='h',
enable_events=True,
disable_number_display=True,
size=(28, 15),
key='pwdCount'),
sg.Text(pdict['pwdCount'], key='-count-')
]
result_option_list = [sg.Listbox(
values=pwds, enable_events=True, key='-listpwd-', size=(50, 15))]
propmsg = [sg.Column(
[], justification='center')]
copyAll = [
sg.Column([], justification='center')]
layout = [[
sg.Frame("参数设置",
,
size=(450, 200))
],
, size=(450, 415))]]
window = sg.Window("随机密码生成器", layout=layout, **optional)
while True:
event, values = window.read()# type: ignore
if event == sg.WIN_CLOSED:
break
if event == 'pwdCount':
window['-count-'].update(value=str(int(values['pwdCount'])))
if event == 'pwdlength':
window['-PWDLEN-'].update(value=str(int(values['pwdlength'])))
if event == 'sym':
window['spclistr'].update(disabled=not values['sym'])
if event in [
'sym', 'numbers', 'lowers', 'uppers', 'pwdlength', 'pwdCount',
'spclistr', '-regeneration-'
]:
pwds = batchPwd(values)
window['-listpwd-'].update(values=pwds)
if event == '-listpwd-':
sec_str = values['-listpwd-']
window['-PropMsg-'].update(value=f"密码: {sec_str} 已经复制到剪切板")
pc.copy(sec_str)
if event == '-COPYAll-':
all_seclist = "\n".join( for i in pwds])
pc.copy(all_seclist)
window['-PropMsg-'].update(value=f"所有密码已经复制到剪切板")
window.close()
if __name__ == "__main__":
main()
本来我是要用pyinstaller 打包的,看到有人已经打包了我就没有上传,如果有需要打包exe可执行文件,请安装pyinstaller模块,
打包命令: pyinstaller -w -F xxxx.py Listentomusic 发表于 2023-12-3 14:04
给楼主提个建议,如果可以点击生成的密码自动复制就好了
嗯,我研究研究 谢谢分享 谢谢大佬,python 爱好者很好的示例 感谢分享😊 谢谢分享 提示:NameError: name 'Optional' is not defined错误 楼主辛苦,感谢提供 不错不错,加一个简单界面,然后生成之后自动复制到剪贴板,并让输入网址和用户名等相关信息并保存,一个密码管理软件就形成了。 随机关键在于随机函数上面,是不是真正随机 52soft 发表于 2023-12-3 07:35
提示:NameError: name 'Optional' is not defined错误
发个截图把,你这个看不出来啥问题