Разделите адрес электронной почты на его имя пользователя и доменное имя.

Это моя первая программа на Python, и я хотел узнать о ней мнения всех. Цель программы — разделить адрес электронной почты на имя пользователя и доменное имя.

import sys
import getopt

argv = sys.argv[1:]

# -------Error Handling-Start----------
try:
    opts, args = getopt.getopt(argv, "l:s:h", ["list ", "single ", "help "])
except getopt.GetoptError as err:
    print(f"{err}n""n"
          "Usage: <Options> <Input> n"
          "-l, --list        Specify a list of emails to be sliced n"
          "-s, --single      Specify a single email to be sliced n"
          "-h, --help        Show options")
    opts = []
# -------Error Handling-End------------

for opt, file_arg in opts:
    if opt in ['-h', '--help']:
        sys.exit("Usage: <Options> <Input> n"
                 "-l, --list        Specify a list of emails to be sliced n"
                 "-s, --single      Specify a single email to be sliced n"
                 "-h, --help        Show options")
# If option -h is present, display MAN page

for opt, email_arg in opts:
    if opt in ['-s', '--single']:
        email = email_arg
        username = email[:email.index('@')]
        domain = email[email.index('@') + 1:]
        print(f"Your username: {username}")
        print(f"Your domain name: {domain}n")
# If option -s is present, split input email into username and domain then print the output

for opt, file_arg in opts:
    if opt in ['-l', '--list']:
        file = file_arg

        email_file = open(file, "r")

        for string in email_file:
            username = string[:string.index('@')]
            domain = string[string.index('@') + 1:]
            print(f"Your username: {username}")
            print(f"Your domain name: {domain}")
# If option -l is present read file specified then loop through each line while splitting each into username and domain

if len(sys.argv) == 1:
    sys.exit("Usage: <Options> <Input> n"
             "-l, --list        Specify a list of emails to be sliced n"
             "-s, --single      Specify a single email to be sliced n"
             "-h, --help        Show options")
# If only one argument is supplied, print MAN page.

1 ответ
1

Общий стиль выглядит хорошо. Самая большая возможность для улучшения — это использование вами getopt. Вам следует использовать более новую и простую argparse вместо. Большая часть вашего кода используется для анализа и использования аргументов командной строки. Все это можно сделать в трех строках с argparse.

import argparse

arg_parser = argparse.ArgumentParser()
arg_parser.add_argument("-f", "--file", dest="file", default=False, action="store_true")
arg_parser.add_argument("input", type=str)
args = arg_parser.parse_args()

Вместо того, чтобы использовать --single или же --list, Я добавил один флаг --file (или же -f), поскольку первый вариант не только неоднозначен (что произойдет, если вы не укажете ни один из них или оба?), но и потенциально вводит в заблуждение их имя. Параметр справки с «-h» вводится автоматически.

"-f", "--file" — это флаги, которые вы можете использовать для указания этого аргумента. dest=file означает, что созданный объект args будет иметь атрибут args.file в котором хранится полученное значение. action="store_true" означает, что флаг должен быть указан без значения (т. е. -f вместо -f True), чтобы установить его.

После этого вы можете получить доступ к своим входам как к строкам (потому что type=str) к args.input (потому что первый аргумент add_argument был "input").

open файла всегда следует сочетать с close когда вы закончите его использовать, то же самое верно и для других объектов ввода-вывода, таких как сетевые соединения. Вместо того, чтобы звонить вручную close, лучше использовать контекстные менеджеры Python с with ключевое слово, которое автоматически выполняет любую очистку.

if args.file:
    with open(args.input, "r") as file:
        emails = file.readlines()
else:
    emails = [args.input]

Ваш код для разделения электронной почты на имя пользователя и домен может быть выполнен с помощью str.split, предполагая, что существует ровно один «@». Если нет «@» или больше одного, вам, вероятно, все равно следует уведомить пользователя об ошибке. Если вы хотите иметь реальный «серьезный» код, который запускается в производство в действующей системе, см. Комментарий Тоби Спейта о том, как это правильно сделать.

    if email.count("@") != 1:
        ...  # Notify the user
    username, domain = email.split("@")
    print(f"Your username: {username}")
    print(f"Your domain name: {domain}")

Наконец, ваше использование sys.exit это неверно. Вы должны использовать только sys.exit(n) с целым числом n. sys.exit(0) означает «успешно», все остальное — «не удалось». Если у вас нет особых потребностей, sys.exit(1) это вариант отказа по умолчанию.

Чтобы отображать удобные сообщения об ошибках, проще всего использовать print. Вы можете отображать сообщения как сообщение об ошибке, указав file=sys.stderr (в отличие от значения по умолчанию file=sys.stdout).

        print(f"{email} is not a valid email.", file=sys.stderr)
        sys.exit(1)

В целом, вот как могла бы выглядеть ваша программа:

import sys
import argparse

arg_parser = argparse.ArgumentParser()
arg_parser.add_argument("-f", "--file", dest="file", default=False, action="store_true")
arg_parser.add_argument("input", type=str)
args = arg_parser.parse_args()

if args.file:
    with open(args.input, "r") as file:
        emails = file.readlines()
else:
    emails = [args.input]

for email in emails:
    if email.count("@") != 1:
        print(f"{email} is not a valid email.", file=sys.stderr)
        sys.exit(1)
    username, domain = email.split("@")
    print(f"Your username: {username}")
    print(f"Your domain name: {domain}")

  • 1

    Мне пришлось бы поискать соответствующий RFC (5322, в наши дни?), Чтобы узнать, @ разрешено в локальной части. Если да, то мы захотим найти последний @ для идентификации домена. Вокруг очень много сломанного кода для обработки электронной почты (я часто сталкиваюсь с системами, которые думают, что им разрешено изменять регистр локальной части!), И я бы не хотел поощрять более широкое внедрение теми, кто не может или не хочет прочтите RFC.

    — Тоби Спейт

  • 1

    Я думаю, вы неправильно прочитали код — --single кажется, принимает аргументы, и --list средства читать из файла. Я думаю, что их можно было бы переименовать, как показывает ваша интерпретация!

    — Тоби Спейт

  • 1

    @TobySpeight Вы совершенно правы относительно аргументов. Я обновлю свой ответ, чтобы показать правильное поведение. Что касается RFC5322, то вы тоже правы. Хотя я думаю, что это должно быть скорее примечанием: «Если вам действительно нужна серьезная и безопасная система, не пытайтесь реализовать парсер электронной почты самостоятельно». Если углубляться в детали, я считаю, что на этом уровне обзор выходит за рамки.

    — Андреас Т.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *