Utilities
Along with argument parsing and handling,Click provides several add-on functionalities.
Printing to Stdout:
The echo() function works similar to print command of Python 2 and 3.The main difference is
that it works the same way in Python 2 and 3, intelligently detects misconfigured output
streams and never fails(but has limitations in Python 3).
import click
click.echo("Hello World")
Most importantly, it can print both Unicode and binary data, unlike the built-in print
function in Python 3, which cannot output any bytes. It will, however, emit a trailing
newline by default, which needs to be suppressed by passing nl=False:
click.echo(b'\xe2\x98\x83', nl=False)
Last but not least echo() uses click%u2019s intelligent internal output streams to stdout and
stderr which support unicode output on the Windows console. This means for as long as you
are using click.echo you can output unicode character (there are some limitations on the
default font with regards to which characters can be displayed). This functionality is new
in Click 6.0.
Starting with Click 3.0 you can also easily print to standard error by passing err=True:
click.echo('Hello World!', err=True)
ANSI Colors
Starting with Click 2.0, the echo() function gained extra functionality to deal with ANSI
colors and styles. Note that on Windows, this functionality is only available if colorama
is installed. If it is installed, then ANSI codes are intelligently handled. Note that in
Python 2, the echo function doesn%u2019t parse color code information from bytearrays.
Example below uses a click function called style():
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))
The combination of echo() and style() is also available in a single function called secho():
click.secho('Hello World!', fg='green')
Pager Support
To show longer text on the terminal and make it scrollable, echo_via_pager() function is
used.It works similarly to the echo() function, but always writes to stdout and, if
possible, through a pager.
Example:
@click.command()
def cli():
click.echo_via_pager('\n'.join('Line %d' % idx
for idx in range(200)))
If you want to use the pager for a lot of text, especially if generating everything in
advance would take a lot of time, you can pass a generator (or generator function) instead
of a string:
def _generate_output():
for idx in range(50000):
yield "Line %d\n" % idx
@click.command()
def cli():
click.echo_via_pager(_generate_output())
Screen Clearing
The screen clearing facility is available through click.clear()
Getting Characters
When reading standard input, it won't show up until the line has been terminated because
its is a buffered input.But in cases where you want to read individual characters as they
are being written, Click provides a function called getchar().This function returns the
character in Unicode.Note that this function will always read from the terminal, even if
stdin is instead a pipe.
Example:
import click
click.echo('Continue? [yn] ', nl=False)
c = click.getchar()
click.echo()
def cli():
if c == 'y':
click.echo('We will go on')
elif c == 'n':
click.echo('Abort!')
else:
click.echo('Invalid input :(')
Waiting for Key Press
The pause() function in Click allows the program to pause until it receives an input from
the user.This is especially useful on Windows where cmd.exe will close the window at the
end of the command execution by default, instead of waiting.
Example:
import click
def cli():
click.pause()
Run the code above :
$mytool
Press any key to continue ...
$
Launching Editor
Click supports launching editors automatically through edit(). This is very useful for
asking users for multi-line input. It will automatically open the user%u2019s defined editor
or fall back to a sensible default. If the user closes the editor without saving, the
return value will be None otherwise the entered text.
Example:
import click
def cli():
lines = '# Everything below is ignored\n'
message = click.edit('\n\n' + lines)
if message is not None:
return message.split(lines, 1)[0].rstrip('\n')
You can also launch editor for a file
import click
def cli():
click.edit(filename='input.txt')
Launching Applications
Click has launch() function to launch applications ,locate and select files and open
webpages.
Example:
click.launch("input.txt", locate=True)
click.launch("https://www.google.com")
Printing Filenames
The format_filename() function converts the filename to Unicode to be able to use it with
strings easily.
Example:
click.echo('Path: %s' % click.format_filename(b'input.txt'))
Standard Streams:
Since there are API differences between 2.x and 3.x, especially with regards to how the IO streams respond to Unicode and binary data,Click provides the get_binary_stream() and get_text_stream() functions, which produce consistent results with different Python versions and terminal types. This results in a functional stream object with rare exceptions.
Example:
import click
stdin_text = click.get_text_stream('stdin')
stdout_binary = click.get_binary_stream('stdout')
Intelligent File Opening:
The open_file() function of Click 3.0 can open both stdout/in streams and files.
import click
filename='input.txt'
def cli():
stdout = click.open_file('-', 'w')
test_file = click.open_file('test.txt', 'w')
with click.open_file(filename, 'w') as f:
f.write('Hello World!\n')
Finding Application Folders
Click provides a get_app_dir() function which returns the most appropriate location for
per-user config files for your application depending on the OS.In the example below, the
configuration file for Firefox is located and read and it prints the contents of the
file i.e. profiles.ini :
import os
import configparser
from configparser import RawConfigParser
import click
APP_NAME = 'Firefox'
def cli():
cfg = os.path.join(click.get_app_dir(APP_NAME), 'profiles.ini')
print(cfg)
parser = configparser.RawConfigParser()
parser.read([cfg])
rv = {}
for section in parser.sections():
for key, value in parser.items(section):
rv['%s.%s' % (section, key)] = value
return rv
Output we get is the path of the config file and the sections and key, value pairs in
the file as below:
$mytool
/Users/ranjitgrewal/Library/Application Support/Firefox/profiles.ini
{'General.startwithlastprofile': '1', 'Profile0.name': 'default', 'Profile0.isrelative':
'1', 'Profile0.path': 'Profiles/uwwhoc57.default', 'Profile0.default': '1'}
Progress Bar
Click supports simple progress bar rendering for that through the progressbar() function.
The basic usage is very simple: the idea is that you have an iterable that you want to
operate on. For each item in the iterable it might take some time to do processing. A
label can be associated with the progress bar which will be shown preceding the progress
bar.But there might be cases when the progress bar needs to be advanced irregularly based
on an external iterator .The example below illustrates this where it downloads url using
requests, writes to an output file and the progress bar shows the progress.
import click
import requests
def cli():
label='Downloading webpage.....'
url = 'https://buildmedia.readthedocs.org/media/pdf/pocoo-click/latest/pocoo-click.pdf'
dest='ouput.txt'
r = requests.get(url, stream=True)
length = int(r.headers.get('content-length'))
chunk_size = 28
iter_size = 0
with open(dest, 'wb') as fd:
with click.progressbar(length=length, label=label) as bar:
for chunk in r.iter_content(chunk_size):
fd.write(chunk)
iter_size += chunk_size
bar.update(chunk_size)
Output is :
Downloading webpage..... [####################################] 100%
Comments