Python argparse parse_args в глобальное пространство имен (или причина, по которой это плохая идея)

Я в основном использовал argparse для создания сценариев командной строки в python, и обычно я использую идиому, что я назначаю аргументы как атрибуты объекта, а затем анализирую их по отдельности для переменной, которая соответствует имени их атрибута. Это кажется немного повторяющимся. Есть ли способ назначить их всех в глобальное пространство имен и вырезать шаг назначения; или как часто бывает, когда какое-то поведение python кажется мне нелогичным, может ли какой-нибудь мудрый эксперт по python указать, что есть веская причина, по которой я не должен этого делать или хочу делать это?

Что у меня сейчас есть, это:

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--db",type=str, dest='db', nargs='?', default="test")
    parser.add_argument("--collection",type=str, dest='collection', nargs='?', help="Collection, default is test", default="test")
    args = parser.parse_args()
    db = args.db                   # gross! 
    collection = args.collection   # yuck!
    print(db)
    print(collection)

Что я хотел бы это:

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--db",type=str, dest='db', nargs='?', default="test")
    parser.add_argument("--collection",type=str, dest='collection', nargs='?', help="Collection, default is test", default="test")
    parser.SUPER_parse_args() # now, db and collection are already in the namespace!
    print(db)
    print(collection)

Это не так уж и много, когда у меня только 2 аргумента, но если у меня их 10 или около того, удвоение шагов присваивания, когда я переименовываю в глобальное пространство имен атрибуты, которые уже существуют в объекте args, начинает меня беспокоить.

3 ответа

Решение

Вы можете сделать это используя globals:

globals().update(args.__dict__)

однако, вы действительно *не должны этого делать. Из дзен питона,

Пространства имен - одна из отличных идей - давайте сделаем больше!

Я повторю то, что @Martijn сказал в своем комментарии:

Не. Просто не надо. Я бы использовал args прямо вместо.

Держите вещи как можно лучше отделенными друг от друга. Это делает код более понятным и легким для понимания.

Это то, что я сделал. Это помогает с переменным столкновением, но не ремонтопригодностью.

parser_args = parser.parse_args()
if parser_args.verbose:
    globals().update(argparse.Namespace(verbose=parser_args.verbose).__dict__)

Добавить к ответу Мильсона:

Рассмотреть возможность использования locals().update(args.__dict__) вместо; это обновит текущее пространство имен, а не глобальное пространство имен.

Вы также можете сделать это, используя locals() или vars(). См. Этот пост переполнения стека для хорошего объяснения разницы между ними.

Я немного опаздываю на Mittonchops, но, надеюсь, это поможет другим.

Другие вопросы по тегам