支付宝扫一扫付款
微信扫一扫付款
(微信为保护隐私,不显示你的昵称)
当执行长时间运行的命令时,显示进度信息可能是有益的,它会在你的命令运行时更新:
要显示进度细节,使用 ProgressBar
,传给它一个单元(unit)总数,然后在命令执行时,推进(advance)进度:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | use Symfony\Component\Console\Helper\ProgressBar;
// create a new progress bar (50 units)
// 创建一个新的进度条(50单元)
$progress = new ProgressBar($output, 50);
// start and displays the progress bar
// 启动并显示进度条
$progress->start();
$i = 0;
while ($i++ < 50) {
// ... do some work / 做一些事
// advance the progress bar 1 unit
// 推进进度条一个单位
$progress->advance();
// you can also advance the progress bar by more than 1 unit
// 你也可以用一个以上的单位来推进进度条
// $progress->advance(3);
}
// ensure that the progress bar is at 100%
// 确保进度条达到100%
$progress->finish(); |
不同于使用步数来推进条子 (即使用 advance()
方法),你还可以通过 setProgress()
方法来设置当前的总进度。
如果你的系统不支持 ANSI codes,更新进度条时会添加一个新行。要防止output溢出,调整相应的 setRedrawFrequency()
。默认时,当使用 max
时,重绘频率(redraw frequency)被设为你的 max
值的 10%。
如果你不知道要推进的总步数,在创建 ProgressBar
实例时可直接忽略step参数:
1 | $progress = new ProgressBar($output); |
这时进度将被动态显示:
1 2 3 4 5 6 7 8 9 10 | # no max steps (displays it like a throbber)
# 不提供最大步数时(动态指示)
0 [>---------------------------]
5 [----->----------------------]
5 [============================]
# max steps defined / 定义了max steps时
0/3 [>---------------------------] 0%
1/3 [=========>------------------] 33%
3/3 [============================] 100% |
当任务完成,不要忘记调用 finish()
以便进度条的显示被刷新为100%的完成度。
默认时,在进度条上渲染的信息取决于当前 OutputInterface
实例的冗长度级别(verbosity level):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # OutputInterface::VERBOSITY_NORMAL (CLI with no verbosity flag)
0/3 [>---------------------------] 0%
1/3 [=========>------------------] 33%
3/3 [============================] 100%
# OutputInterface::VERBOSITY_VERBOSE (-v)
0/3 [>---------------------------] 0% 1 sec
1/3 [=========>------------------] 33% 1 sec
3/3 [============================] 100% 1 sec
# OutputInterface::VERBOSITY_VERY_VERBOSE (-vv)
0/3 [>---------------------------] 0% 1 sec
1/3 [=========>------------------] 33% 1 sec
3/3 [============================] 100% 1 sec
# OutputInterface::VERBOSITY_DEBUG (-vvv)
0/3 [>---------------------------] 0% 1 sec/1 sec 1.0 MB
1/3 [=========>------------------] 33% 1 sec/1 sec 1.0 MB
3/3 [============================] 100% 1 sec/1 sec 1.0 MB |
如果你使用静默旗标(-q
)来调用命令,进度条将不被显示。
若不想受到当前命令的冗长模式约束,你还可以通过 setFormat()
来强制格式输出:
1 | $bar->setFormat('verbose'); |
有以下内置格式:
normal
verbose
very_verbose
debug
如果你没有设置进度条的总步数,使用 _nomax
变体:
normal_nomax
verbose_nomax
very_verbose_nomax
debug_nomax
不使用内置格式(built-in formats)时,可以设置你自己的:
1 | $bar->setFormat('%bar%'); |
它设置的是只显示进度条本身
1 2 3 | >---------------------------
=========>------------------
============================ |
进度条格式(prgress bar format),就是包含了特定占位符(被 %
括起的名称)的一个字符串;占位符将根据条子的当前进度被替换掉。以下是内置占位符的列表:
current
: The current step(当前步数);max
: 最大步数 (未定义时是0);bar
: 条子本身;percent
: 进度完成的百分比 (max未定义时不可用);elapsed
: 启动进度条后流经的时间;remaining
: 完成任务的剩余时间 (max未定义时不可用);estimated
: 预期的完成任务时间 (max未定义时不可用);memory
: 当前内存占用;message
: 当前进度条上的附加信息例如,这里有一个如何去设置一个和 debug
相同的格式之样例:
1 | $bar->setFormat(' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%'); |
注意到被添加到某些占位符的 :6s
部分了吗?这就是你如何去调整条子外观 (包括格式和排列等)的方法。冒号 (:
) 后面的部分用于设置字符串的 sprintf
格式。
message
占位符有些特殊,因为你必须自行设置它的值:
1 2 3 4 5 6 7 8 9 10 | $bar->setMessage('Task starts');
$bar->start();
$bar->setMessage('Task in progress...');
$bar->advance();
// ...
$bar->setMessage('Task is finished');
$bar->finish(); |
若不想对给定的进度条实例去设置格式,你可以设置全局格式(global formats):
1 2 3 4 | ProgressBar::setFormatDefinition('minimal', 'Progress: %percent%%');
$bar = new ProgressBar($output, 3);
$bar->setFormat('minimal'); |
以上代码定义了一个全新的 minimal
格式,你可以用在自己的进度条中:
1 2 3 | Progress: 0%
Progress: 33%
Progress: 100% |
重新的定义内置格式总是好过自行创造一种。因为它可以让你基于“命令的冗长级别旗标”来自动进行多样化显示。
要定义一个包含了“最大步数已知时才可用”的占位符之全新风格时,你应该创建一个 _nomax
变体:
1 2 3 4 5 | ProgressBar::setFormatDefinition('minimal', '%percent%% %remaining%');
ProgressBar::setFormatDefinition('minimal_nomax', '%percent%%');
$bar = new ProgressBar($output);
$bar->setFormat('minimal'); |
显示进度条时,该格式将被自动设置为 minimal_nomax
,如果条子并没有一个“最大步数”的话,就像上例中的代码。
一个格式(formata)可以包含任何有效的ANSI字符,也可以使用Symfony的特定方式来设置颜色:
1 2 3 4 | ProgressBar::setFormatDefinition(
'minimal',
'<info>%percent%</info>\033[32m%\033[0m <fg=white;bg=blue>%remaining%</>'
); |
一个格式,可以扩展为多行;当你希望在进度条旁边显示更多的上下文信息时,这特别有用(参考本文开头部分)。
在所有占位符中,bar
有点特殊,因为所有用于显示它的占位符都可以被自定义:
1 2 3 4 5 6 7 8 9 10 11 | // the finished part of the bar / 条子的已完成部分
$progress->setBarCharacter('<comment>=</comment>');
// the unfinished part of the bar / 条子的未完成部分
$progress->setEmptyBarCharacter(' ');
// the progress character / 进度之字符
$progress->setProgressCharacter('|');
// the bar width / 条子宽度
$progress->setBarWidth(50); |
出于性能原因,在设置较高数值的总步数时要小心。例如,如果你遍历的是大量元素,考虑调用 setRedrawFrequency()
来将重绘频率设为一个高值,以便它只在少量的循环中被更新:
so it updates on only some iterations:
1 2 3 4 5 6 7 8 9 10 11 12 | $progress = new ProgressBar($output, 50000);
$progress->start();
// update every 100 iterations / 每100次循环更新一次
$progress->setRedrawFrequency(100);
$i = 0;
while ($i++ < 50000) {
// ... do some work / 处理一些事
$progress->advance();
} |
如果你希望显示一些取决于 “在内置占位符列表中不可用” 的进度条显示 之信息,你可以创建自己的。看一下如何创建 remaining_steps
占位符,用来显示剩余的步数:
1 2 3 4 5 6 | ProgressBar::setPlaceholderFormatterDefinition(
'remaining_steps',
function (ProgressBar $bar, OutputInterface $output) {
return $bar->getMaxSteps() - $bar->getProgress();
}
); |
%message%
占位符允许你指定一个自定义消息,它会和进度条一起显示出来。但如果你需要更多条消息,只需定义你自己的:
1 2 3 4 5 6 7 8 9 10 11 12 13 | $bar->setMessage('Task starts');
$bar->setMessage('', 'filename');
$bar->start();
$bar->setMessage('Task is in progress...');
while ($file = array_pop($files)) {
$bar->setMessage($filename, 'filename');
$bar->advance();
}
$bar->setMessage('Task is finished');
$bar->setMessage('', 'filename');
$bar->finish(); |
对于让 filename
成为进度条的一部分,只需添加 %filename%
占位符到你的format中:
1 | $bar->setFormat(" %message%\n %current%/%max%\n Working on %filename%"); |
本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。