Spec-Zone.ru › click

Утилиты

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

Вывод в стандартный вывод

Наиболее очевидной вспомогательной функцией является echo(), которая во многом работает так же, как оператор или функция Python print. Основное различие заключается в том, что она работает одинаково во многих различных терминальных средах.

Пример:

import click

click.echo('Hello World!')

Она может выводить как текстовые, так и двоичные данные. По умолчанию она выводит символ новой строки, который необходимо подавить, передав nl=False.

click.echo(b'\xe2\x98\x83', nl=False)

Наконец, echo() использует интеллектуальные внутренние потоки вывода click для stdout и stderr, которые поддерживают вывод Unicode в консоли Windows. Это означает, что пока вы используете click.echo, вы можете выводить символы Unicode (есть некоторые ограничения на шрифт по умолчанию относительно того, какие символы могут быть отображены).

Изменения

Введено в версии 6.0.

Click эмулирует потоки вывода в Windows для поддержки Unicode в консоли Windows через отдельные API. Дополнительную информацию см. в Примечания к консоли Windows.

Изменения

Введено в версии 3.0.

Вы также можете легко выводить данные в стандартный поток ошибок, передав err=True.

click.echo('Hello World!', err=True)

ANSI цвета

Изменения

Введено в версии 2.0.

Функция echo() поддерживает ANSI цвета и стили. В Windows для этого используется colorama.

В основном это означает, что:

  • Функция Click’s echo() автоматически удаляет ANSI коды цветов, если поток не подключен к терминалу.
  • функция echo() прозрачно подключается к терминалу в Windows и преобразует ANSI коды в вызовы API терминала. Это означает, что цвета будут работать в Windows так же, как и в других операционных системах.

В Windows Click использует colorama без вызова colorama.init(). Вы по-прежнему можете вызвать его в своем коде, но это не требуется для Click.

Для стилизации строки можно использовать функцию style():

import click

click.echo(click.style('Hello World!', fg='green'))
click.echo(click.style('Some more text', bg='blue', fg='white'))
click.echo(click.style('ATTENTION', blink=True, bold=True))

Сочетание echo() и style() также доступно в одной функции, называемой secho():

click.secho('Hello World!', fg='green')
click.secho('Some more text', bg='blue', fg='white')
click.secho('ATTENTION', blink=True, bold=True)

Поддержка пейджера

В некоторых ситуациях вам может потребоваться отобразить длинные тексты в терминале и позволить пользователю прокручивать их. Этого можно добиться, используя функцию echo_via_pager(), которая работает аналогично функции echo(), но всегда записывает в stdout и, при возможности, через пейджер.

Пример:

@click.command()
def less():
    click.echo_via_pager("\n".join(f"Line {idx}" for idx in range(200)))

Если вы хотите использовать пейджер для большого количества текста, особенно если предварительное создание всего займет много времени, вы можете передать генератор (или функцию-генератор) вместо строки:

def _generate_output():
    for idx in range(50000):
        yield f"Line {idx}\n"

@click.command()
def less():
    click.echo_via_pager(_generate_output())

Очистка экрана

Изменения

Введено в версии 2.0.

Для очистки экрана терминала можно использовать функцию clear(), доступную начиная с Click 2.0. Она делает то, что подразумевается названием: очищает весь видимый экран независимо от платформы:

import click
click.clear()

Получение символов из терминала

Изменения

Введено в версии 2.0.

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

Для этого Click предоставляет функцию getchar(), которая считывает один символ из буфера терминала и возвращает его как символ Unicode.

Обратите внимание, что эта функция всегда считывает данные с терминала, даже если stdin является каналом.

Пример:

import click

click.echo('Continue? [yn] ', nl=False)
c = click.getchar()
click.echo()
if c == 'y':
    click.echo('We will go on')
elif c == 'n':
    click.echo('Abort!')
else:
    click.echo('Invalid input :(')

Обратите внимание, что это считывает необработанный ввод, что означает, что такие вещи, как стрелки, будут отображаться в формате escape, специфичном для платформы. Переводятся только символы ^C и ^D, которые соответственно преобразуются в исключения прерывания клавиатуры и конца файла. Это сделано потому, что в противном случае слишком легко забыть об этом и создать скрипты, которые нельзя правильно завершить.

Ожидание нажатия клавиши

Изменения

Введено в версии 2.0.

Иногда полезно приостановить выполнение, пока пользователь не нажмет любую клавишу на клавиатуре. Это особенно полезно в Windows, где cmd.exe по умолчанию закрывает окно в конце выполнения команды вместо ожидания.

В click это можно сделать с помощью функции pause(). Эта функция выводит быстрое сообщение в терминал (которое можно настроить) и ожидает нажатия пользователем клавиши. Кроме того, она также станет инструкцией NOP (операция без действия), если скрипт не запускается в интерактивном режиме.

Пример:

import click
click.pause()

Запуск редакторов

Изменения

Введено в версии 2.0.

Click поддерживает автоматический запуск редакторов через edit(). Это очень полезно для запроса многострочного ввода у пользователя. Он автоматически откроет определенный пользователем редактор или вернется к разумному значению по умолчанию. Если пользователь закроет редактор без сохранения, возвращаемое значение будет None, в противном случае – введенный текст.

Пример использования:

import click

def get_commit_message():
    MARKER = '# Everything below is ignored\n'
    message = click.edit('\n\n' + MARKER)
    if message is not None:
        return message.split(MARKER, 1)[0].rstrip('\n')

Кроме того, функция также может использоваться для запуска редакторов для файлов по заданному имени файла. В этом случае возвращаемое значение всегда None.

Пример использования:

import click
click.edit(filename='/etc/passwd')

Запуск приложений

Изменения

Введено в версии 2.0.

Click поддерживает запуск приложений через launch(). Это можно использовать для открытия приложения по умолчанию, связанного с URL-адресом или типом файла. Например, это можно использовать для запуска веб-браузеров или просмотрщиков изображений. Кроме того, это также может запустить файловый менеджер и автоматически выбрать предоставленный файл.

Пример использования:

click.launch("https://click.palletsprojects.com/")
click.launch("/my/downloaded/file.txt", locate=True)

Вывод имён файлов

Поскольку имена файлов могут не быть Unicode, форматирование может быть немного сложным.

В Click это работает с помощью функции format_filename(). Она делает все возможное, чтобы преобразовать имя файла в Unicode и никогда не потерпит неудачу. Это позволяет использовать эти имена файлов в контексте полной строки Unicode.

Пример:

click.echo(f"Path: {click.format_filename(b'foo.txt')}")

Стандартные потоки

Для утилит командной строки очень важно надежно получить доступ к потокам ввода и вывода. Python обычно предоставляет доступ к этим потокам через sys.stdout и аналогичные, но, к сожалению, существуют различия в API между версиями 2.x и 3.x, особенно в том, как эти потоки реагируют на Unicode и двоичные данные.

Из-за этого Click предоставляет функции get_binary_stream() и get_text_stream(), которые обеспечивают согласованный результат в разных версиях Python и для широкого спектра конфигураций терминалов.

В конечном итоге эти функции всегда возвращают функциональный объект потока (за исключением очень редких случаев; см. Поддержка Unicode).

Пример:

import click

stdin_text = click.get_text_stream('stdin')
stdout_binary = click.get_binary_stream('stdout')
Изменения

Введено в версии 6.0.

Click теперь эмулирует потоки вывода в Windows для поддержки Unicode в консоли Windows через отдельные API. Дополнительную информацию см. в Примечания к консоли Windows.

Умное открытие файлов

Журнал изменений

Новое в версии 3.0.

Начиная с Click 3.0, логика открытия файлов типа File реализована через функцию open_file(). Она умеет умно открывать stdin/stdout, а также любые другие файлы.

Пример:

import click

stdout = click.open_file('-', 'w')
test_file = click.open_file('test.txt', 'w')

Если возвращаются stdin или stdout, то возвращаемое значение обернуто в специальный файл, где менеджер контекста предотвратит закрытие файла. Это делает обработку стандартных потоков прозрачной, и вы всегда можете использовать её так:

with click.open_file(filename, 'w') as f:
    f.write('Hello World!\n')

Поиск папок приложения

Журнал изменений

Новое в версии 2.0.

Часто требуется открыть файл конфигурации, относящийся к приложению. Однако разные операционные системы хранят эти файлы конфигурации в разных местах в зависимости от своих стандартов. Click предоставляет функцию get_app_dir(), которая возвращает наиболее подходящее расположение файлов конфигурации для каждого пользователя вашего приложения в зависимости от ОС.

Пример использования:

import os
import click
import ConfigParser

APP_NAME = 'My Application'

def read_config():
    cfg = os.path.join(click.get_app_dir(APP_NAME), 'config.ini')
    parser = ConfigParser.RawConfigParser()
    parser.read([cfg])
    rv = {}
    for section in parser.sections():
        for key, value in parser.items(section):
            rv[f"{section}.{key}"] = value
    return rv

Отображение полос прогресса

Иногда у вас есть скрипты командной строки, которые обрабатывают много данных, но вы хотите быстро показать пользователю некоторую информацию о том, сколько времени это займёт. Click поддерживает отображение простых полос прогресса для этого через функцию progressbar().

Примечание

Если вам нужны возможности, которые не поддерживает полоса прогресса Click, попробуйте использовать tqdm.

Основное использование очень простое: идея заключается в том, что у вас есть итерируемый объект, над которым вы хотите работать. Для каждого элемента в итерируемом объекте может потребоваться некоторое время для обработки. Предположим, у вас есть цикл такого вида:

for user in all_the_users_to_process:
    modify_the_user(user)

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

import click

with click.progressbar(all_the_users_to_process) as bar:
    for user in bar:
        modify_the_user(user)

Click затем автоматически отобразит полосу прогресса в терминале и рассчитает оставшееся время для вас. Для расчёта оставшегося времени требуется, чтобы у итерируемого объекта была длина. Если у него нет длины, но вы знаете её, вы можете явно её указать:

with click.progressbar(all_the_users_to_process,
                       length=number_of_users) as bar:
    for user in bar:
        modify_the_user(user)

Обратите внимание, что progressbar() обновляет полосу после каждой итерации цикла. Поэтому код такого вида отобразится корректно:

import time

with click.progressbar([1, 2, 3]) as bar:
    for x in bar:
        print(f"sleep({x})...")
        time.sleep(x)

Ещё одна полезная функция — назначение метки полосе прогресса, которая будет отображаться перед полосой прогресса:

with click.progressbar(all_the_users_to_process,
                       label='Modifying user accounts',
                       length=number_of_users) as bar:
    for user in bar:
        modify_the_user(user)

Иногда может потребоваться итерироваться по внешнему итератору и обновлять полосу прогресса нерегулярно. Для этого вам нужно указать длину (и не использовать итерируемый объект) и использовать метод update на контекстном возвращаемом значении вместо прямого итерирования:

with click.progressbar(length=total_size,
                       label='Unzipping archive') as bar:
    for archive in zip_file:
        archive.extract()
        bar.update(archive.size)

© Copyright 2014 Pallets.
Licensed under the BSD 3-Clause License.
We are not supported nor endorsed by Pallets.
https://click.palletsprojects.com/en/8.1.x/utils/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API