bing52 发表于 2023-12-2 18:06

用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:48

本帖最后由 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

bing52 发表于 2023-12-3 14:59

Listentomusic 发表于 2023-12-3 14:04
给楼主提个建议,如果可以点击生成的密码自动复制就好了

嗯,我研究研究

q197843 发表于 2023-12-3 02:21

谢谢分享

InnocenceYv 发表于 2023-12-3 02:32

谢谢大佬,python 爱好者很好的示例

wyh138 发表于 2023-12-3 05:25

感谢分享&#128522;

ysf216 发表于 2023-12-3 07:16

谢谢分享

52soft 发表于 2023-12-3 07:35

提示:NameError: name 'Optional' is not defined错误

jinqiaoa1a 发表于 2023-12-3 08:34

楼主辛苦,感谢提供

Manray 发表于 2023-12-3 09:35

不错不错,加一个简单界面,然后生成之后自动复制到剪贴板,并让输入网址和用户名等相关信息并保存,一个密码管理软件就形成了。

jyjjf 发表于 2023-12-3 10:18

随机关键在于随机函数上面,是不是真正随机

bing52 发表于 2023-12-3 10:47

52soft 发表于 2023-12-3 07:35
提示:NameError: name 'Optional' is not defined错误

发个截图把,你这个看不出来啥问题
页: [1] 2 3 4 5
查看完整版本: 用python写了一个随机密码生成器,分享一下