Создание приложения командной строки в python с помощью Click

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

Вот код, который у меня есть до сих пор.

привет.py

import click

@click.version_option(1.0)

@click.command()
@click.argument('string', default='World')
@click.option('-r', '--repeat', default=1, help='How many times should be greeted.')

def cli(string,repeat):
    '''This string greets you.'''
    for i in xrange(repeat): 
        click.echo('Hello %s!' % string)

if __name__ == '__main__':
    cli()

Когда я запускаю его.

$ привет

Hello World!

$ привет Боб

Hello Bob!

$ привет Боб -r 3

Hello Bob!
Hello Bob!
Hello Bob!

Это именно то, что я хочу.

Теперь я хотел бы иметь возможность принимать ввод со стандартного ввода, как в следующих примерах.

$ эхо Джон | привет

Hello John!

$ эхо Джон | привет -r 3

Hello John!
Hello John!
Hello John!

person Ishan    schedule 18.10.2015    source источник


Ответы (2)


Ну, это довольно старый вопрос, но я все равно постараюсь ответить на него.

Я новичок в Click, поэтому, думаю, мое решение можно значительно улучшить. В любом случае он делает именно то, что вы хотите. Вот:

import click


def get_name(ctx, param, value):
    if not value and not click.get_text_stream('stdin').isatty():
        return click.get_text_stream('stdin').read().strip()
    else:
        return value


@click.command()
@click.argument('name', callback=get_name, required=False)
@click.option('--repeat', '-r', default=1)
def say_hello(name, repeat):
    for i in range(repeat):
        click.echo('Hello {}'.format(name or 'World'))



if __name__ == "__main__":
    say_hello()
person BigBear    schedule 23.08.2017

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

Если вы хотите, чтобы ваше приложение было "конвейерным", просто вставьте в него raw_input, так как эта функция читает со стандартного ввода.

Чтобы ваша программа выглядела как кошка, вы можете сделать:

@click.command()
@click.argument('string', required=False)
@click.option('-r', '--repeat', default=1, help='How many times should be greeted.')
def cli(string, repeat):
    '''This string greets you.'''
    if not string:
        string = raw_input()
    for i in xrange(repeat):
        click.echo('Hello %s!' % string)

Другой вариант - преобразовать строку в параметр и установить для приглашения значение True:

@click.command()
@click.option('--string', prompt=True)
@click.option('-r', '--repeat', default=1, help='How many times should be greeted.')
def cli(string, repeat):
    '''This string greets you.'''
    for i in xrange(repeat):
        click.echo('Hello %s!' % string)

Таким образом, если пользователь не предоставит строку, ему будет предложено ввести данные, что также сделает ваше приложение конвейерным. Единственная проблема заключается в том, что он будет печатать на стандартный вывод STRING:, что иногда неприемлемо (вы можете определить пустую строку для отображения с помощью prompt='', но, насколько я знаю, нет возможности избавиться от :).

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

python hello.py `echo bob`

echo bob будет оцениваться первым, и его результат будет составлять аргументы для hello.py

person ppalacios    schedule 25.10.2015