Как сделать кнопку в консоли python

Обновлено: 04.07.2024

Для создания кнопки используется конструктор Button() . В этом конструкторе с помощью параметра text можно установить текст кнопки:

Чтобы сделать элемент видимым, у него вызывается метод pack() . В итоге вверху окна будет красоваться кнопка:

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

Параметры bg - background и fg - foreground получают значение цвета. Результат выполнения:

Всего же конструктор Button может принимать следующие параметры:

Параметр master представляет ссылку на родительский контейнер. В случае выше это могло бы быть само графическое окно, и мы могли написать:

Однако если в коде создается одно окно, то кнопка и любой другой элемент уже по умолчанию размещаются в этом окне. Поэтому первый параметр можно опустить, как в примерах выше. Если бы у нас в коде создавалось бы несколько окон, тогда мы могли бы передать в Button(root) ссылку на нужное окно.

Второй параметр options представляет набор параметров, которые мы можем установить по их имени:

  • activebackground : цвет элемента, когда он находится в нажатом состоянии;
  • activefontground : цвет текста элемента, когда он в нажатом состоянии;
  • bd : толщина границы (по умолчанию 2);
  • bg/background : фоновый цвет;
  • fg/fontground : цвет текста;
  • font : шрифт текста, например, font= «Arial 14» - шрифт Arial высотой 14px , или font=(«Verdana», 13, «bold») - шрифт Verdana высотой 13px с выделением жирным;
  • height : высота элемента;
  • highlightcolor : цвет элемента, когда она в фокусе;
  • image : изображение на элементе;
  • justify : устанавливает выравнивание текста. Значение LEFT выравнивает текст по левому краю, CENTER - по центру, RIGHT - по правому краю;
  • padx : отступ от границ элемента до ее текста справа и слева;
  • pady : отступ от границ элемента до ее текста сверху и снизу;
  • relief : определяет тип границы, может принимать значения SUNKEN, RAISED, GROOVE, RIDGE;
  • state : устанавливает состояние элемента, может принимать значения DISABLED, ACTIVE, NORMAL (по умолчанию);
  • text : устанавливает текст элемента;
  • textvariable : устанавливает привязку к элементу StringVar ;
  • underline : указывает на номер символа в тексте элемента, который подчеркивается. По умолчанию значение -1, то есть никакой символ не подчеркивается;
  • width : ширина элемента;
  • wraplength : при положительном значении строки текста будут переносится для вмещения в пространство элемента.

Имена переменным нужно задавать корректно: состоят из двух слов (или более), отражающих суть содержания объекта, слова соединяются нижним подчеркиванием.

Python — невероятно гибкий язык программирования, который хорошо интегрируется с существующими программами. Немало Python-кода написано в виде скриптов и интерфейсов командной строки (CLI).

Инструменты и интерфейсы командной строки — эффективная вещь, так как они позволяют автоматизировать практически всё что угодно. Как следствие, эти интерфейсы с течением времени могут стать довольно сложными.

Обычно всё начинается с простого скрипта на Python, который что-то делает. Например, получает доступ к веб-API и выводит результат в консоль:

Вы можете запустить этот скрипт с помощью команды python3 print_user_agent.py , и он выведет имя user-agent, использованного для вызова API.

Sportmaster Lab , Санкт-Петербург , От 170 000 до 250 000 ₽

Как и было сказано, довольно простой скрипт.

Но что делать, когда подобная программа растёт и становится всё более сложной?

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

Используя эти знания, мы шаг за шагом перейдём от простого скрипта к интерфейсу командной строки с аргументами, опциями и полезными инструкциями по использованию. Всё это мы сделаем с помощью библиотеки click.

К концу этой статьи вы будете знать:

  • Почему click — лучшая альтернатива argparse и optparse;
  • Как с его помощью создать простой CLI;
  • Как добавить обязательные аргументы командной строки в ваши скрипты;
  • Как парсить флаги и опции командной строки;
  • Как сделать ваши консольные приложения более удобными, добавив справочный текст.

Вы увидите, как сделать всё это с минимальным количеством шаблонного кода.

Примечание переводчика Код в данной статье написан на Python 3.6, работоспособность на более ранних версиях не гарантируется.

Зачем вам писать скрипты и инструменты для командной строки на Python?

Код выше – всего лишь пример, не очень полезный в реальной жизни. На самом деле скрипты бывают куда более сложные. Возможно, вы имели опыт с ними и знаете, что они могут быть важной частью нашей повседневной работы: некоторые скрипты остаются на протяжении всего времени жизни проекта, для которого они были написаны. Некоторые начинают приносить пользу другим командам или проектам. У них даже может расширяться функционал.

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

Здесь приходят на выручку такие модули, как optparse и argparse, которые делают нашу жизнь на порядок проще. Но прежде чем мы с ними познакомимся, давайте разберёмся с терминологией.

Основы интерфейса командной строки

Интерфейс командной строки (CLI) начинается с имени исполняемого файла. Вы вводите имя в консоль и получаете доступ к главной точке входа скрипта, такого как pip.

В зависимости от сложности CLI обычно есть определённые параметры, которые вы можете передавать скрипту:

  1. Аргумент, который является обязательным параметром. Если его не передать, то CLI вернёт ошибку. Например, в следующей команде click является аргументом: pip install click .
  2. Опция – необязательный параметр, который объединяет имя и значение, например --cache-dir ./my-cache . Вы говорите CLI, что значение ./my-cache должно использоваться как директория для кэша.
  3. Флаг, который включает или выключает определённый сценарий. Вероятно, самым частым является --help . Вы только указываете имя, а CLI самостоятельно интерпретирует значение.

С более сложными CLI, такими как pip или Heroku CLI, вы получаете доступ к набору функций, которые собраны под главной точкой входа. Они обычно называются командами или подкомандами.

Возможно, вы уже использовали CLI, когда устанавливали Python-библиотеку с помощью команды pip install <имя пакета> . Команда install говорит CLI, что вы хотите использовать функцию установки пакета, и даёт вам доступ к параметрам, характерным для этой функции.

Пакеты для работы с командной строкой, доступные в стандартной библиотеке Python 3.x

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

Два наиболее известных пакета для этого — optparse и argparse. Они являются частью стандартной библиотеки Python и добавлены туда по принципу «всё включено».

По большей части они делают одно и то же и работают схожим образом. Главное отличие заключается в том, что optparse не используется начиная с Python 3.2, и argparse считается стандартом для создания CLI в Python.

Вы можете узнать о них больше в документации Python, но, чтобы иметь представление, как выглядит скрипт с argparse, посмотрите на пример ниже:

click против argparse: лучшая альтернатива?

Вероятно, вы смотрите на этот код и думаете: «Что это всё значит?» И это является одной из проблем argparse: код с ним неинтуитивен и сложночитаем.

Поэтому вам может понравиться click.

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

С click легко создавать многофункциональный CLI с небольшим количеством кода. И этот код будет легко читаться, даже когда ваш CLI вырастет и станет более сложным.

Пишем простой CLI на Python с помощью click

Вдоволь поговорив о CLI и библиотеках, давайте взглянем на пример, чтобы понять, как написать простой CLI с click. Как и в первом примере, мы создаём простой CLI, который выводит результат в консоль. Это несложно:

Не пугайтесь последних двух строк: это то, как Python запускает функцию main при исполнении файла как скрипта.

Более реалистичный пример CLI на Python с использованием click

Теперь, когда вы знаете, как click упрощает написание CLI, давайте взглянем на более реалистичный пример. Мы напишем программу, которая позволяет нам взаимодействовать с веб-API.

API, который мы дальше будем использовать, — OpenWeatherMap API. Он предоставляет информацию о текущей погоде, а также прогноз на пять дней для определённого местоположения. Мы начнём с тестового API, который возвращает текущую погоду для места.

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

Если вы смущены наличием API-ключа в примере сверху, не переживайте, это тестовый API-ключ, предоставляемый сервисом.

  • q — место, в котором мы хотим узнать погоду;
  • appid — наш API-ключ.

Это позволяет нам создать простую реализацию на Python с использованием библиотеки requests (опустим обработку ошибок и неудачных запросов для простоты):

Эта функция делает простой запрос к API, используя два параметра. В качестве обязательного аргумента она принимает location (местоположение), которое должно быть строкой. Также мы можем указать API-ключ, передавая параметр api_key при вызове функции. Это необязательно, так как по умолчанию используется тестовый ключ.

И вот мы видим текущую погоду в Python REPL:

Парсим обязательные параметры с click

Простая функция current_weather позволяет нам создать CLI с местоположением, указанным пользователем. Это должно работать примерно так:

Как вы, возможно, догадались, местоположение — это аргумент, поскольку оно является обязательным параметром для нашего погодного CLI.

Как нам сделать это при помощи click? Всё довольно просто, мы используем декоратор под названием argument . Кто бы мог подумать?

Давайте возьмём наш предыдущий пример и слегка изменим его, добавив аргумент location :

Если этот print выглядит для вас странно, не волнуйтесь — это новый способ форматирования строк в Python 3.6+, который называется f-форматированием.

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

Примечание переводчика Имя аргумента, переданное click, должно совпадать с именем аргумента в объявлении функции.

В нашем случае значение аргумента командной строки location будет передано функции main в качестве аргумента location . Логично, не так ли?

Также вы можете использовать тире в именах, например api-key , которые click переведёт в snake case для имени аргумента в функции, например main(api_key) .

Реализация main просто использует нашу функцию current_weather для получения погоды в указанном месте. И затем мы с помощью print выводим полученную информацию.

Парсим опциональные параметры с click

Как вы, возможно, догадались, тестовый API ограничивает нас в возможностях. Поэтому, прежде чем мы продолжим, зарегистрируйтесь и получите настоящий API-ключ.

Первое, что нам нужно изменить, — URL, откуда берутся данные о текущей погоде. Это можно сделать, изменив значение переменной url в функции current_weather на URL, указанный в документации OpenWeatherMap:

Это изменение приведёт к неработоспособности нашего CLI, так как указанный API-ключ не работает с реальным API. Поэтому давайте добавим новый параметр в наш CLI, который позволит нам указывать API-ключ. Но сначала мы должны решить, будет ли этот параметр аргументом или опцией. Мы сделаем его опцией, так как добавление параметра вроде --api-key делает его более явным и говорящим за себя.
Мы хотим, чтобы наша программа запускалась таким образом:

Проще простого. Посмотрим, как добавить опцию к нашей существующей команде:

И снова мы добавляем декоратор к нашей функции main . В этот раз мы используем декоратор с говорящим именем @click.option и указываем имя для нашей опции, начинающееся с двух тире. Как вы видите, мы также можем указать сокращение для нашей опции с одним тире, чтобы сэкономить пользователю немного времени.

Как было сказано ранее, click создаёт аргумент для передачи в функцию main из длинного варианта имени. В случае с опцией он убирает впередистоящие тире и переводит её в snake case. Таким образом, --api-key становится api_key .

Чтобы всё заработало, осталось лишь передать API-ключ в функцию current_weather .

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

Добавляем автоматически генерируемые инструкции по использованию

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

Сначала давайте проверим, что выведет флаг --help после всех сделанных изменений. Довольно неплохо, учитывая что мы не приложили к этому никаких усилий:

Второе (и последнее), что мы сделаем, — добавим документацию для всей click-команды. Самый простой и самый питонический способ сделать это — добавить строку документации в нашу функцию main . Да, нам в любом случае нужно сделать это, поэтому это не лишняя работа:

Сложив всё вместе, мы получаем хороший вывод для нашего инструмента:

Подводим итоги

Итак, в этом уроке мы рассмотрели много всего. Можете гордиться собой, вы написали свой собственный CLI, и всё это с минимальным количеством шаблонного кода! Исходный код ниже доказывает это. Не стесняйтесь использовать его для собственных экспериментов:

Одно из главных преимуществ создания приложения с Tkinter в том, что с его помощью очень просто настроить интерфейс всего в несколько строк. И если программа становится сложнее, то и сложнее логически разделять ее на части, а организованная структура помогает сохранять код в чистом виде.

Простой пример

Возьмем в качестве примера следующую программу:

Она создает окно с кнопкой, которая выводит Привет, Tkinter! каждый раз при нажатии. Кнопка расположена с внутренним отступом 120px по горизонтальной оси и 30px – по вертикальной. Последняя строка запускает основной цикл, который обрабатывает все пользовательские события и обновляет интерфейс до закрытия основного окна.

Простое окно с кнопкой

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

Wildcard-импорты ( from … import * ) считаются плохой практикой, поскольку они загрязняют глобальное пространство имен. Здесь они используются для иллюстрации анти-паттерна, который часто встречается в примерах онлайн.

Эти проблемы настройки решаются с помощью базовых техник объектно-ориентированного программирования, что считается хорошей практикой для любых типов программ на Python.

Правильный пример

Чтобы улучшить модуль простой программы, стоит определить несколько классов, которые станут обертками вокруг глобальных переменных:

Теперь каждая переменная хранится в конкретной области видимости, включая функцию command , которая находится в отдельном методе.

Как работает это приложение?

Во-первых нужно заменить wildcard-импорт на импорт в формате import … as для лучшего контроля над глобальным пространством имен.

Затем класс App определяется как подкласс Tk , который теперь ссылается на пространство имен tk . Для правильной инициализации базового класса, вызывается метод __init__() класса Tk с помощью встроенной функции super() . За это отвечают следующие строки:

Теперь есть ссылка на экземпляр App с переменной self . Так что виджет кнопки будет добавлен как атрибут класса.

Это может казаться излишним для такой простой программы, но подобный рефакторинг помогает работать с каждой отдельной частью. Создание кнопки отделено от обратного вызова, которые исполняется при нажатии. А генерация приложения перемещена в if __name__ == "main" , что является стандартной практикой для исполняемых скриптов в Python.

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

Дополнение о структуре приложения

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

Однако может быть более удобно разделять классы Frame или Toplevel особенно для больших программ, где, например, есть несколько окон. Это все потому что у приложения Tkinter должен быть один экземпляр Tk , а система создает их автоматически при создании экземпляра виджета до создания экземпляра самого Tk .

Помните, что это не влияет на структуру класса App , поскольку у всех классов виджетов есть метод mainloop , который запускает основной цикл Tk .

Работа с кнопками

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

Как создать кнопку

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

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

После выполнения кода выше, возвращается следующее:

Разные варианты настройки кнопок

Простейший способ создания экземпляра Button — использование параметра text для настройки метки кнопки и command , который ссылается на вызываемую функцию при нажатии кнопки.

В этом примере также добавляется PhotoImage с помощью параметра image , который имеет приоритет над строкой text . Этот параметр используется для объединения изображения и текста на одной кнопке, определяя местоположение, где будет находиться картинка. Он принимает следующие константы: CENTER, BOTTOM, LEFT, RIGHT и TOP.

Второй ряд кнопок создается с помощью сгенерированного списка и списка значений RELIEF . Метка каждой кнопки соответствует константе, так что можно заметить разницу во внешнем виде.

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

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

Звезда активна
Звезда активна
Звезда активна
Звезда не активна
Звезда не активна

Для того, чтобы создать кнопку в Python 3 с обработкой нажатия мыши, понадобится использовать пакет или библиотеку tkinter. По сути tkinter package является стандартным интерфейсом Python для инструментария Tk GUI. Поэтому его можно использовать для создания кнопки. Для осваивания данного языка это будет интересная и полезная практика. Для начала следует импортировать данный пакет и протестировать был ли он установлен в используемой вами среде разработки.

Установить tkinter в Линуксе (Убунту) можно через терминал (вызов терминала: Alt-Ctrl-T) набрав в терминале sudo apt-get install python3-tk. Там же в терминале можно узнать и установленную версию Питона (python - v).

Протестировать и узнать установлен ли tkinter в среде разработки можно следующим образом:

Самый простой пример кнопки без обработчика нажатия мыши можно прописать так:

Ещё пример простой до безобразия кнопки в Python 3:

Создание кнопки в Python 3 при помощи tkinter

А вот интересный пример, в котором сразу три кнопки в одном фрейме (окне) при помощи библиотеки tkinter:

Импорт пакета как tk (сокращённо). Импорт библиотеки времени.

Создание окна, в котором будут отображаться кнопки. master — родительский виджет. pack () — упаковщик для размещения блоков один под другим. Создание виджета.

сommand прописывает обращение к методу нажатия мыши на кнопку. Упаковщик pack необходим для размещения блоков один над другим.

Создание второй кнопки Выхода из программы в том же методе создания виджета. Создание кнопки выхода из программы с удалением всех виджетов. Упаковщик для размещения блоков один под другим.

Обработка нажатия мыши. Создание кнопки с указанием времени на ней на данный момент. Обращение к методу при нажатии на кнопку, который выведет актуальное на данный момент время.

Метод нажатия кнопки. Создание метода для вывода информации после нажатия на кнопку.

Создание метода, который выведет актуальное на данный момент время.

Создание собственного окна.

Создание экземпляра класса.

Запуск главного цикла обработки событий.

А вот и полностью весь код примера трёх кнопок, который по кусочкам описан выше:

Читайте также: