After giving a couple of well-received answers to similar questions, I thought I'd try to come up with my own solution.
I believe that a good password generator can and should be quite simple without sacrificing security or usability.
Also, this is the first time I actually code a command-line utility (as a Windows user, command-line tools aren't part of my usual work-flow).
I'm interested in any remark about my code, especially regarding security and features.
'''
Command-line utility program for generating passwords
'''
from argparse import ArgumentParser, RawTextHelpFormatter
import secrets
from string import ascii_lowercase, ascii_uppercase, digits, punctuation
ESCAPES = { r'\l' : ascii_lowercase,
            r'\u' : ascii_uppercase,
            r'\d' : digits,
            r'\s' : punctuation }
def generate_password(length, alphabet):
    return ''.join(secrets.choice(alphabet) for _ in range(length))
def _parse_alphabet(specifiers):
    ranges = []
    for escape, characters in ESCAPES.items():
        if escape in specifiers:
            ranges.append(characters)
            specifiers = specifiers.replace(escape, '')
    ranges.append(specifiers)
    return ''.join(set(''.join(ranges)))
if __name__ == '__main__':
    parser = ArgumentParser(
        prog='Password generator',
        formatter_class=RawTextHelpFormatter)
    parser.add_argument(
        '-l', '--length',
        default=32,
        type=int,
        help='length of password to be generated')
    parser.add_argument(
        '-a', '--alphabet',
        default=r'\l\u\d\s',
        help=r'''alphabet to use for password generation. The following escape sequences are supported:
    * \u: uppercase ASCII letters.
    * \l: lowercase ASCII letters.
    * \d: digits.
    * \s: other printable ASCII characters.
Any other specified character will also be included.''')
    args = parser.parse_args()
    print(generate_password(args.length, _parse_alphabet(args.alphabet)))
Example uses:
# show help
(base) [...]>python password.py -h
usage: Password generator [-h] [-l LENGTH] [-a ALPHABET]
optional arguments:
  -h, --help            show this help message and exit
  -l LENGTH, --length LENGTH
                        length of password to be generated
  -a ALPHABET, --alphabet ALPHABET
                        alphabet to use for password generation. The following escape sequences are supported:
                            * \u: uppercase ASCII letters.
                            * \l: lowercase ASCII letters.
                            * \d: digits.
                            * \s: other printable ASCII characters.
                        Any other specified character will also be included.
# generate a password with default settings:
(base) [...]>python password.py
y3S%iR!O=zNhcWYf-f9@87m_FC'WGr+^
# generate a 6-digit PIN (eg. for phone unlocking):
(base) [...]>python password.py -l 6 -a \d
310696
# generate a password with smaller length and only some special chars (eg. for website compatibility):
(base) [...]>python password.py -l 16 -a "\u\l\d_-&@!?"
bP7L?_uuGbdHFww@
# generate a long password:
(base) [...]>python password.py  -l 250
FO_Hy1O,7#z}M'5K/,=:Al"dK-w{VIC:G$[Xqm|GRw8Uou@d^peD1vk$:76)n#28f112w"vz<F+-c\it$7@fb9Xq@3\[)7+*R7PTa(gdMb&\,?n6GRT93jD'L!6Ww)u:-}rWyXq&?V!pw>9<&.Nt4S!+a9X6f~z+?DZeB:);`-!{K;ftB(/;"TEeKi%yV,-,H3{2!x2Y"]'?[3$/'QM=K5mSo[!D~#;!iuY]=BF3=LLkGK92Nm4kttc\*S
# generate a password with non-ASCII characters:
(base) [...]>python password.py -a µùûÜ
ùùùÜùùµÜܵµµÜùûÜûµÜÜÜûûÜûûùùùûܵ
