2015-05-02 2 views
1

Я очень новичок в этом модуле, поэтому, пожалуйста, несите меня. У меня есть следующий код:Создайте парсер с подкомандами в argparse, настройте позиционные аргументы

reader.py

import argparse 

parent_parser = argparse.ArgumentParser(description="Read text files.") 
parent_parser.add_argument('filename', help='TXT file', type=file, nargs='+') 
parent_parser.add_argument('--verbose', '-v', action='store_true', 
     help="Verbosity on") 

child_parser = parent_parser.add_subparsers(title="subcommand", 
     help="Subcommand help") 
new_file_command = child_parser.add_parser('new', help="New text file") 
edit_file_command = child_parser.add_parser('edit', help="Edit existing text file") 

args = parent_parser.parse_args() 

То, что я пытаюсь достичь не может быть стандартным способом, как парсеры и UNIX утилиты командной строки работают. Если это правда, пожалуйста, исправьте меня, поскольку я хотел бы иметь стандартизованное приложение.

Это то, что я пытаюсь достичь:

  • если вы запустите скрипт с голой позиционной аргумент (ы), как это: python reader.py some.txt Я хотел бы иметь возможность просто разобрать его и передать его функция, которая читает текстовый файл, конечно, я хочу принять необязательный аргумент arg verbose, а также
  • , если вы запустите подкоманду 'new' (new_file_command), я не хочу иметь позиционный аргумент filename, но я хочу пройти строку и создать новый текстовый файл следующим образом: python reader.py new another.txt
  • , если вы запустите субкоманду «редактировать» (edit_file_command) Я хочу, чтобы передать существующий файл в пути и проверить для него (как вы используете type=int в add_argument), а затем, возможно, передать его функции, которая открывает редактор, что-то вроде этого: python reader.py edit some.txt

Опять же, я не уверен, что именно так должны работать приложения/сценарии командной строки. Я прочитал документы и посмотрел примеры, но мне все еще не ясно, как работают парсеры. Я попробовал посмотреть модуль Click, но мне кажется еще сложнее.

Любая помощь приветствуется. Благодаря!

ответ

2

Так три образца звонки:

python reader.py some.txt 
python reader.py new another.txt 
python reader.py edit some.txt 

Самый простой способ справиться с этим является одним «дополнительным» позиционной, и один требуемого.

parser = ArgumentParser... 
parser.add_argument('-v','--verbose', ...) 
parser.add_argument('cmd', nargs='?', default='open', choices=['open','edit','new']) 
parser.add_argument('filename') 

Для ваших 3-й образцов, она должна производить что-то вроде:

namespace(cmd='open', filename='some.txt') 
namespace(cmd='new', filename='another.txt') 
namespace(cmd='edit', filename='some.txt') 

cmd является дополнительным аргументом позиционным. Если он отсутствует, одна строка будет выделена filename, а cmd получит свой default. Это проще сделать, чем пытаться сделать необязательным subparsers.


Что касается текущего синтаксического анализа:

parent_parser = argparse.ArgumentParser(description="Read text files.") 
parent_parser.add_argument('filename', help='TXT file', type=file, nargs='+') 

Я бы не рекомендовал использовать type=file. Лучше использовать FileType или строку по умолчанию (которая позволяет вам открыть файл в with context позже).

Что касается nargs='+', вы действительно хотите выделить 1 or more строк на filename? Или вы думали о '?', Который был бы 0 or 1, т. Е. Сделать его необязательным?

parent_parser.add_argument('--verbose', '-v', action='store_true', 
     help="Verbosity on") 

child_parser = parent_parser.add_subparsers(title="subcommand", 
     help="Subcommand help") 
new_file_command = child_parser.add_parser('new', help="New text file") 
edit_file_command = child_parser.add_parser('edit', help="Edit existing text file") 

Смешивание этого filename позиционного, который принимает переменное число значений, с subparsers аргументом (позиционный, который ожидает либо new или edit) может быть проблемой.

Я ожидаю, что 'python reader.py some.txt' возразит, что отсутствует команда subparser. 'python reader.py new another.txt' попытается выделить new в filename, а another.txt - подпункер и поднять ошибку.

Было бы лучше ожидать команду subparsers во всех 3-х случаях:

parent_parser = argparse.ArgumentParser(description="Read text files.") 
parent_parser.add_argument('--verbose', '-v', action='store_true', 
     help="Verbosity on") 
child_parser = parent_parser.add_subparsers(title="subcommand", 
     help="Subcommand help", dest='cmd') 
open_file_command = child_parser.add_parser('open', help="Open text file") 
open_file_command.add_argument('filename', help='TXT file') 
new_file_command = child_parser.add_parser('new', help="New text file") 
new_file_command.add_argument('filename', help='TXT file') 
edit_file_command = child_parser.add_parser('edit', help="Edit existing text file") 
edit_file_command.add_argument('filename', help='TXT file') 

Каждая из команд, «открытый», «новый», «изменить», ожидает «имя файла».

Попытка избежать использования команды open создаст больше трудностей, чем она того стоит.

(Существует ошибка/функция в последнем argparse, что делает subparsers необязательными, но вы не должны воспользоваться тем, что, не зная проблем.)


С:

parser = argparse.ArgumentParser() 
parser.add_argument('-v', '--verbose') 
parser.add_argument('cmd', nargs='?', default='open', 
    choices=['open', 'edit', 'new']) 
parser.add_argument('filename', nargs='+') 

Я ожидаю reader.py new customstring дать

namespace(cmd='new', filename=[customstring]) 

, которые могут быть использованы в качестве:

if args.cmd=='new': 
with open(args.filename[0] + '.txt', 'w') as f: 
    # do something with the newly created file 

open и edit будет использовать различные режимы open.

+0

Привет, спасибо за помощь. У меня есть последний вопрос. Мне все еще интересно, как настраивать позиционные аргументы. Предположим, у меня есть следующий код: parser = argparse.ArgumentParser() parser.add_argument ('- v', '--verbose') parser.add_argument ('cmd', nargs = '?', Default = 'open ', choice = [' open ',' edit ',' new ']) parser.add_argument (' filename ', nargs =' + ') Что делать, если я хочу настроить позиционный arg для команды 'new'? Мне не нужно/нужно передавать явное имя файла, а просто строку типа 'some', а затем она создает файл' some.txt'. Как мне это сделать? Спасибо – user3056783

+0

Вы можете создать пользовательский 'type' или' Action'. Но, как правило, проще сделать такое изменение после разбора. Особенно, если вы не выполняете проверку ошибок на «некоторые». – hpaulj

+0

Привет, я все еще просматриваю документы и пытаюсь понять это, но я не могу найти больше примеров в Интернете. Можете ли вы просто показать мне фрагмент, как вы могли бы реализовать это после разбора? Потому что, если я делаю «reader.py new customstring», он проверяет наличие существующего имени файла, чтобы он не позволял мне ничего делать. – user3056783

Смежные вопросы