知乎专栏 |
self.parser = argparse.ArgumentParser(description='自动切割学习数据') self.parser.add_argument('--source', type=str, default=None, help='图片来源地址') self.parser.add_argument('--target', default=None, type=str, help='图片目标地址') self.parser.add_argument('--imgsz', type=int, default=640, help='长边尺寸',metavar=640) self.parser.add_argument('--clean', action="store_true", default=False, help='清理之前的数据') self.parser.add_argument('--md5sum', action="store_true", default=False, help='使用md5作为文件名') self.parser.add_argument('--uuid', action="store_true", default=False, help='重命名图片为UUID') self.args = self.parser.parse_args()
import argparse parser = argparse.ArgumentParser(description='Simple example') parser.add_argument('name', help='Who to greet', default='World') # Create two argument groups foo_group = parser.add_argument_group(title='Foo options') bar_group = parser.add_argument_group(title='Bar options') # Add arguments to those groups foo_group.add_argument('--bar_this') foo_group.add_argument('--bar_that') bar_group.add_argument('--foo_this') bar_group.add_argument('--foo_that') args = parser.parse_args()
usage: example.py [-h] [--bar_this BAR_THIS] [--bar_that BAR_THAT] [--foo_this FOO_THIS] [--foo_that FOO_THAT] name Simple example positional arguments: name Who to greet optional arguments: -h, --help show this help message and exit Foo options: --bar_this BAR_THIS --bar_that BAR_THAT Bar options: --foo_this FOO_THIS --foo_that FOO_THAT
from termcolor import colored # then use Termcolor for all colored text output print(colored('Hello, World!', 'green', 'on_red'))
import sys from termcolor import colored, cprint text = colored('Hello, World!', 'red', attrs=['reverse', 'blink']) print(text) cprint('Hello, World!', 'green', 'on_red') print_red_on_cyan = lambda x: cprint(x, 'red', 'on_cyan') print_red_on_cyan('Hello, World!') print_red_on_cyan('Hello, Universe!') for i in range(10): cprint(i, 'magenta', end=' ') cprint("Attention!", 'red', attrs=['bold'], file=sys.stderr)
https://pypi.org/project/colorama/
pip install colorama
init(autoreset = False),当 autoreset = True 时自动恢复到默认颜色
#!/usr/bin/env python from colorama import init, Fore, Back, Style if __name__ == "__main__": init(autoreset=True) # 初始化,自动恢复到默认颜色 print(Fore.RED + 'some red text') print(Back.GREEN + 'and with a green background') print(Style.DIM + 'and in dim text')
CLI 和 TUI 开发中我们常常会用到进度条,用于展示下载或执行进度等等。
Bar |################################| 200/200 [2 / 0 / 0:00:00] (None) ChargingBar ████████████████████████████████ 200/200 [2 / 0 / 0:00:00] (None) FillingSquaresBar ▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣ 200/200 [2 / 0 / 0:00:00] (None) FillingCirclesBar ◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉ 200/200 [2 / 0 / 0:00:00] (None) IncrementalBar |████████████████████████████████| 100% [0:00:02 / 0 / 0:00:00] PixelBar |⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿| 100% [0:00:02 / 0 / 0:00:00] ShadyBar |████████████████████████████████| 100% [0:00:02 / 0 / 0:00:00] Corolored |████████████████████████████████| 200/200 Spinner %(index)d - PieSpinner %(index)d ◷ MoonSpinner %(index)d ◑ LineSpinner %(index)d ⎼ PixelSpinner %(index)d ⡿ Counter 100 Countdown 0 Stack █ Pie ● Random |██████████████████████████████▊ | 96
安装
pip install progress
演示
from progress.bar import Bar bar = Bar('Processing', max=20) for i in range(20): # Do some work bar.next() bar.finish()
执行结果
neo@MacBook-Pro-Neo ~/workspace/python % python3.9 progress-demo.py Processing |################################| 20/20
from progress.bar import Bar import time import random length = 100 bar = Bar('Processing', max=length) for i in range(length): # Do some work time.sleep(random.randrange(1, 5)*0.05) bar.next() bar.finish()
运行结果
Processing |######### | 31/100
将 # 换成 @ 符号,并且进度改为百分比。
bar = Bar('Loading', fill='@', suffix='%(percent)d%%') 演示 Loading |@@@@@@@@@@@@@ | 42%
from progress.bar import ChargingBar import time import random length = 100 with ChargingBar('Processing', max=length) as bar: for i in range(length): # Do some work time.sleep(random.randrange(1, 5)*0.05) bar.next()
运行结果
Processing ███████████████████████∙∙∙∙∙∙∙∙∙ 73%
from progress.bar import FillingSquaresBar import time import random length = 100 bar = FillingSquaresBar('Processing', max=length) for i in range(length): # Do some work time.sleep(random.randrange(1, 5)*0.05) bar.next() bar.finish()
运行结果
Processing ▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢ 47%
bar = FillingCirclesBar('Processing', max=length) for i in range(length): # Do some work time.sleep(random.randrange(1, 5)*0.05) bar.next() bar.finish()
运行结果
Processing ◉◉◉◉◉◉◉◉◉◉◉◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯ 41%
from progress.bar import IncrementalBar import subprocess cmd = "/usr/bin/memory_pressure | tail -n 1 | cut -d ':' -f2" usage = 0 p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, bufsize=64) usage = int(p.stdout.readline().decode().replace(' ', '').replace('%', '').replace('\n', '')) p.stdout.close() p.wait() length = 100 bar = IncrementalBar('Memory', max=length, suffix='%(index)d%%') bar.goto(usage) bar.finish()
Memory |████████████████▋ | 52%
安装
neo@MacBook-Pro-Neo ~ % pip install tqdm
neo@MacBook-Pro-Neo ~ % tqdm -h Usage: tqdm [--help | options] Options: -h, --help Print this help and exit. -v, --version Print version and exit. --desc=<desc> : str, optional Prefix for the progressbar. --total=<total> : int or float, optional The number of expected iterations. If unspecified, len(iterable) is used if possible. If float("inf") or as a last resort, only basic progress statistics are displayed (no ETA, no progressbar). If `gui` is True and this parameter needs subsequent updating, specify an initial arbitrary large positive number, e.g. 9e9. --leave : bool, optional If [default: True], keeps all traces of the progressbar upon termination of iteration. If `None`, will leave only if `position` is `0`. --ncols=<ncols> : int, optional The width of the entire output message. If specified, dynamically resizes the progressbar to stay within this bound. If unspecified, attempts to use environment width. The fallback is a meter width of 10 and no limit for the counter and statistics. If 0, will not print any meter (only stats). --mininterval=<mininterval> : float, optional Minimum progress display update interval [default: 0.1] seconds. --maxinterval=<maxinterval> : float, optional Maximum progress display update interval [default: 10] seconds. Automatically adjusts `miniters` to correspond to `mininterval` after long display update lag. Only works if `dynamic_miniters` or monitor thread is enabled. --miniters=<miniters> : int or float, optional Minimum progress display update interval, in iterations. If 0 and `dynamic_miniters`, will automatically adjust to equal `mininterval` (more CPU efficient, good for tight loops). If > 0, will skip display of specified number of iterations. Tweak this and `mininterval` to get very efficient loops. If your progress is erratic with both fast and slow iterations (network, skipping items, etc) you should set miniters=1. --ascii=<ascii> : bool or str, optional If unspecified or False, use unicode (smooth blocks) to fill the meter. The fallback is to use ASCII characters " 123456789#". --disable : bool, optional Whether to disable the entire progressbar wrapper [default: False]. If set to None, disable on non-TTY. --unit=<unit> : str, optional String that will be used to define the unit of each iteration [default: it]. --unit-scale=<unit_scale> : bool or int or float, optional If 1 or True, the number of iterations will be reduced/scaled automatically and a metric prefix following the International System of Units standard will be added (kilo, mega, etc.) [default: False]. If any other non-zero number, will scale `total` and `n`. --dynamic-ncols : bool, optional If set, constantly alters `ncols` and `nrows` to the environment (allowing for window resizes) [default: False]. --smoothing=<smoothing> : float, optional Exponential moving average smoothing factor for speed estimates (ignored in GUI mode). Ranges from 0 (average speed) to 1 (current/instantaneous speed) [default: 0.3]. --bar-format=<bar_format> : str, optional Specify a custom bar string formatting. May impact performance. [default: '{l_bar}{bar}{r_bar}'], where l_bar='{desc}: {percentage:3.0f}%|' and r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, ' '{rate_fmt}{postfix}]' Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt, percentage, elapsed, elapsed_s, ncols, nrows, desc, unit, rate, rate_fmt, rate_noinv, rate_noinv_fmt, rate_inv, rate_inv_fmt, postfix, unit_divisor, remaining, remaining_s, eta. Note that a trailing ": " is automatically removed after {desc} if the latter is empty. --initial=<initial> : int or float, optional The initial counter value. Useful when restarting a progress bar [default: 0]. If using float, consider specifying `{n:.3f}` or similar in `bar_format`, or specifying `unit_scale`. --position=<position> : int, optional Specify the line offset to print this bar (starting from 0) Automatic if unspecified. Useful to manage multiple bars at once (eg, from threads). --postfix=<postfix> : dict or *, optional Specify additional stats to display at the end of the bar. Calls `set_postfix(**postfix)` if possible (dict). --unit-divisor=<unit_divisor> : float, optional [default: 1000], ignored unless `unit_scale` is True. --write-bytes : bool, optional If (default: None) and `file` is unspecified, bytes will be written in Python 2. If `True` will also write bytes. In all other cases will default to unicode. --lock-args=<lock_args> : tuple, optional Passed to `refresh` for intermediate output (initialisation, iterating, and updating). --nrows=<nrows> : int, optional The screen height. If specified, hides nested bars outside this bound. If unspecified, attempts to use environment height. The fallback is 20. --colour=<colour> : str, optional Bar colour (e.g. 'green', '#00ff00'). --delay=<delay> : float, optional Don't display until [default: 0] seconds have elapsed. --delim=<delim> : chr, optional Delimiting character [default: '\n']. Use '\0' for null. N.B.: on Windows systems, Python converts '\n' to '\r\n'. --buf-size=<buf_size> : int, optional String buffer size in bytes [default: 256] used when `delim` is specified. --bytes : bool, optional If true, will count bytes, ignore `delim`, and default `unit_scale` to True, `unit_divisor` to 1024, and `unit` to 'B'. --tee : bool, optional If true, passes `stdin` to both `stderr` and `stdout`. --update : bool, optional If true, will treat input as newly elapsed iterations, i.e. numbers to pass to `update()`. Note that this is slow (~2e5 it/s) since every input must be decoded as a number. --update-to : bool, optional If true, will treat input as total elapsed iterations, i.e. numbers to assign to `self.n`. Note that this is slow (~2e5 it/s) since every input must be decoded as a number. --null : bool, optional If true, will discard input (no stdout). --manpath=<manpath> : str, optional Directory in which to install tqdm man pages. --comppath=<comppath> : str, optional Directory in which to place tqdm completion. --log=<log> : str, optional CRITICAL|FATAL|ERROR|WARN(ING)|[default: 'INFO']|DEBUG|NOTSET.
from tqdm import tqdm import time for i in tqdm(range(100)): time.sleep(0.1) pass
演示效果
neo@MacBook-Pro-Neo ~/workspace/python % python3.9 /Users/neo/workspace/python/terminal/tqdm/demo.py 31%|██████████████▉ | 31/100 [00:03<00:07, 9.66it/s]
from tqdm import tqdm,trange import time for i in trange(100): time.sleep(0.1) pass
from tqdm import tqdm import time length = 50 # total 参数设置进度条的总长度 with tqdm(total=length) as bar: for i in range(length): time.sleep(0.05) # 每次更新进度条的长度 bar.update(1)
from tqdm import tqdm import time length = 50 #total参数设置进度条的总长度 bar = tqdm(total=length) for i in range(length): time.sleep(0.05) #每次更新进度条的长度 bar.update(1) #关闭进度条 bar.close()
from tqdm import tqdm import time bar = tqdm(["加载", "执行", "保存", "完成"]) for step in bar: time.sleep(1) bar.set_description("当前进度 %s" % step)
from tqdm import tqdm import time import random with tqdm(total=100, ncols=100) as progress: progress.set_description("%s" % "netkiller") for n in range(100): time.sleep(random.randrange(1, 5) * 0.05) progress.update(1)
/Users/neo/PycharmProjects/netkiller/.venv/bin/python /Users/neo/PycharmProjects/netkiller/test/test.py netkiller: 100%|██████████████████████████████████████████████████| 100/100 [00:13<00:00, 7.60it/s]
from time import sleep from tqdm import trange, tqdm import multiprocessing import random threads = list(range(5)) total = 100 def run(n): name = multiprocessing.current_process().name description = "#{} - {}".format(n, name) for i in trange(total, desc=description, position=n, ascii=True): sleep(random.randrange(1, 9)*0.1) if __name__ == '__main__': pool = multiprocessing.Pool(len(threads)) pool.map(run, threads) pool.close() pool.join()
效果展示
#0 - SpawnPoolWorker-1: 9%|######### | 9/100 [00:04<00:45, 1.98it/s] #1 - SpawnPoolWorker-4: 10%|#########9 | 10/100 [00:04<00:44, 2.01it/s] #2 - SpawnPoolWorker-2: 13%|############8 | 13/100 [00:04<00:34, 2.54it/s] #3 - SpawnPoolWorker-3: 10%|#########9 | 10/100 [00:04<00:50, 1.78it/s] #4 - SpawnPoolWorker-5: 14%|#############8 | 14/100 [00:04<00:28, 2.99it/s]
pip install alive-progress
from alive_progress import alive_bar import time items = range(10) # retrieve your set of items with alive_bar(len(items)) as bar: # declare your expected total for item in items: # iterate as usual # process each item bar() # call after consuming one item time.sleep(1)
效果展示
|████████████████ | ▇▅▃ 4/10 [40%] in 3s (1.2/s, eta: 4s)
import tempfile import httpx import rich.progress with tempfile.NamedTemporaryFile() as download_file: url = "https://speed.hetzner.de/100MB.bin" with httpx.stream("GET", url) as response: total = int(response.headers["Content-Length"]) with rich.progress.Progress( "[progress.percentage]{task.percentage:>3.0f}%", rich.progress.BarColumn(bar_width=None), rich.progress.DownloadColumn(), rich.progress.TransferSpeedColumn(), ) as progress: download_task = progress.add_task("Download", total=total) for chunk in response.iter_bytes(): download_file.write(chunk) progress.update(download_task, completed=response.num_bytes_downloaded)
https://github.com/foutaise/texttable/
pip install texttable
程序演示
from texttable import Texttable table = Texttable() table.add_rows([["Name", "Age", "Nickname"], ["Neo", 35, "netkiller"], ["李磊", 23, "Lee"], ["韩美美", 28, "May"]]) print(table.draw())
+--------+-----+-----------+ | Name | Age | Nickname | +========+=====+===========+ | Neo | 35 | netkiller | +--------+-----+-----------+ | 李磊 | 23 | Lee | +--------+-----+-----------+ | 韩美美 | 28 | May | +--------+-----+-----------+
max_width 设置报格最大宽度
table = Texttable(max_width= 160) table.add_rows(tables) print(table.draw())
set_header_align(self, array) 设置水平对齐
set_cols_align(self, array) 设置水平对齐
set_cols_valign(self, array) 设置垂直对齐
from texttable import Texttable table = Texttable() table.set_cols_align(["l", "r", "c"]) table.set_cols_valign(["t", "m", "b"]) table.add_rows([["Name", "Age", "Nickname"], ["Mr\nXavier\nHuon", 32, "Xav'"], ["Mr\nBaptiste\nClement", 1, "Baby"], ["Mme\nLouise\nBourgeau", 28, "Lou\n\nLoue"]]) print(table.draw()) print()
输出结果
+----------+-----+----------+ | Name | Age | Nickname | +==========+=====+==========+ | Mr | | | | Xavier | 32 | | | Huon | | Xav' | +----------+-----+----------+ | Mr | | | | Baptiste | 1 | | | Clement | | Baby | +----------+-----+----------+ | Mme | | Lou | | Louise | 28 | | | Bourgeau | | Loue | +----------+-----+----------+
from texttable import Texttable table = Texttable() for header in (Texttable.BORDER, Texttable.HEADER, Texttable.HLINES, Texttable.VLINES): table.set_deco(header) table.set_cols_align(["l", "r", "c"]) table.set_cols_valign(["t", "m", "b"]) table.add_rows([["Name", "Age", "Nickname"], ["Neo", 35, "netkiller"], ["李磊", 23, "Lee"], ["韩美美", 28, "May"]]) print(table.draw()) print("\n\n")
输出结果
+--------------------------+ | Name Age Nickname | | Neo 35 netkiller | | 李磊 23 Lee | | 韩美美 28 May | +--------------------------+ Name Age Nickname ======================== Neo 35 netkiller 李磊 23 Lee 韩美美 28 May Neo 35 netkiller 李磊 23 Lee 韩美美 28 May Name Age Nickname Neo 35 netkiller +--------------------------+ 李磊 23 Lee +--------------------------+ 韩美美 28 May +--------------------------+ Neo 35 netkiller +--------------------------+ 李磊 23 Lee +--------------------------+ 韩美美 28 May +--------------------------+ Neo 35 netkiller +--------------------------+ 李磊 23 Lee +--------------------------+ 韩美美 28 May Name | Age | Nickname Neo | 35 | netkiller 李磊 | 23 | Lee 韩美美 | 28 | May Neo | 35 | netkiller 李磊 | 23 | Lee 韩美美 | 28 | May Neo | 35 | netkiller 李磊 | 23 | Lee 韩美美 | 28 | May Neo | 35 | netkiller 李磊 | 23 | Lee 韩美美 | 28 | May
自定义行列线条字符
set_chars(self, array) | Set the characters used to draw lines between rows and columns | | - the array should contain 4 fields: | | [horizontal, vertical, corner, header] | | - default is set to: | | ['-', '|', '+', '=']
set_chars(self, array) 数字的四个参数分别是:
默认是 ['-', '|', '+', '=']
下面这段代码模仿 MySQL 终端输出样式
table = Texttable() table.set_cols_align(["r", "l", "c", "l", "l"]) table.set_cols_valign(["m", "m", "m", "m", "m"]) table.set_chars(['-', '|', '+', '-']) table.set_cols_dtype(['i', 't', 'i', 't', 'a']) table.add_rows([["id", "name", "age", "nickname", "ctime"], [1, "Neo", 35, "netkiller", "2021-05-16 10:14:00"], [2, "Tom", 23, "Lee", "2021-05-16 10:14:00"], [3, "Jerry", 28, "May", "2021-05-16 10:14:00"]]) print(table.draw()) print()
+----+-------+-----+-----------+---------------------+ | id | name | age | nickname | ctime | +----+-------+-----+-----------+---------------------+ | 1 | Neo | 35 | netkiller | 2021-05-16 10:14:00 | +----+-------+-----+-----------+---------------------+ | 2 | Tom | 23 | Lee | 2021-05-16 10:14:00 | +----+-------+-----+-----------+---------------------+ | 3 | Jerry | 28 | May | 2021-05-16 10:14:00 | +----+-------+-----+-----------+---------------------+
怎么样,似曾相识吧?跟 mysql 命令中输出结果一致。
from texttable import Texttable table = Texttable() table.set_deco(Texttable.HEADER) table.set_cols_dtype(['t', # text 'f', # float (decimal) 'e', # float (exponent) 'i', # integer 'a']) # automatic table.set_cols_align(["l", "r", "r", "r", "l"]) table.add_rows([["text", "float", "exp", "int", "auto"], ["abcd", "67", 654, 89, 128.001], ["efghijk", 67.5434, .654, 89.6, 12800000000000000000000.00023], ["lmn", 5e-78, 5e-78, 89.4, .000000000000128], ["opqrstu", .023, 5e+78, 92., 12800000000000000000000]]) print(table.draw())
输出结果
text float exp int auto ============================================== abcd 67.000 6.540e+02 89 128.001 efghijk 67.543 6.540e-01 90 1.280e+22 lmn 0.000 5.000e-78 89 0.000 opqrstu 0.023 5.000e+78 92 1.280e+22
texttable 本身不支持 ANSI 彩色文本输出,我以修复了该 Bug,已经想修复代码pull request 给作者。
Pull Request: https://github.com/foutaise/texttable/pull/75
我的代码库地址: https://github.com/netkiller/texttable
from texttable import Texttable from colorama import Fore, Back, Style, init table = Texttable() table.set_chars(['-', '|', '+', '-']) # table.set_cols_width([8, 5, 19]) table.add_rows([["Name", "Age", "Nickname"], ["Neo", 35, Fore.RED+"netkiller"+Fore.RESET], ["李磊", 23, Fore.GREEN+"Lee"+Fore.RESET], ["韩美美", 28, Fore.BLUE+"May"+Fore.RESET]]) print(table.draw())