【问题标题】:Printing on screen the percentage completed while my tcl script is running?在我的 tcl 脚本运行时在屏幕上打印完成的百分比?
【发布时间】:2012-11-29 22:02:45
【问题描述】:

我有一个需要几分钟才能运行的 tcl 脚本(执行时间因配置不同而异)。

我希望用户对它是否仍在执行以及在脚本执行期间完成需要多长时间有所了解。

到目前为止我的一些想法:

1) 使用 ... 表示它随着每个内部命令运行左右而不断增加。但同样,它并没有真正让第一次使用的用户知道还有多少。

2) 使用我在很多地方见过的旋转斜线。

3) 在屏幕上显示实际完成百分比。不知道这是否可行或如何去做。

是否有人对可以做些什么有任何想法,以便脚本的用户了解正在发生的事情以及如何做到这一点?

另外,如果我使用 ... 来实现它,我如何让他们打印 .每次都在同一行。如果我在 tcl 脚本中使用 puts 来执行此操作,则 .只是打印在下一行。

对于旋转斜线,我需要替换已经打印在屏幕上的东西。我怎么能用 tcl 做到这一点?

【问题讨论】:

  • 我尝试将 -nonewline 选项与 puts 一起使用。但这只是在脚本末尾打印出所有点,而不是在执行过程中一个一个打印出来。这就是我尝试过的 puts -nonewline "."

标签: shell io tcl


【解决方案1】:

标准输出流最初是行缓冲的,因此在您写入换行符、调用flush 或关闭它(脚本退出时自动完成)之前,您不会看到新的输出。您可以使用...关闭此缓冲。

fconfigure stdout -buffering none

...但是诊断、错误、消息、进度等确实应该写入stderr 流。它默认将缓冲设置为无,因此您不需要 fconfigure。

【讨论】:

    【解决方案2】:

    首先,您在打印点时遇到问题的原因是 Tcl 正在缓冲其输出,等待新行。这通常是一种有用的行为(通常足以使其成为默认行为)但在这种情况下不需要它,因此您可以使用以下命令将其关闭:

    fconfigure stdout -buffering none
    

    (其他缓冲选项是linefull,它们提供逐渐更高级别的缓冲以提高性能但降低响应速度。) 或者,在打印一个点后执行flush stdout。 (或者将点打印到stderr,默认情况下是无缓冲的,主要用于错误消息。)

    做一个微调器并不比打印点难多少。关键技巧是使用回车(一个不可打印的字符,有时可视为^M)将光标位置移回行首。将微调器代码分解成一个小程序是很好的:

    proc spinner {} {
        global spinnerIdx
        if {[incr spinnerIdx] > 3} {
            set spinnerIdx 0
        }
        set spinnerChars {/ - \\ |}
        puts -nonewline "\r[lindex $spinnerChars $spinnerIdx]"
        flush stdout
    }
    

    那么您需要做的就是定期致电spinner。简单! (另外,完成后在微调器上打印一些内容;只需执行puts "\r$theOrdinaryMessage"。)

    一直到一个实际的进度表是很好的,它建立在这些技术之上,但它需要你计算出有多少处理要做等等。微调器更容易实现! (特别是如果你还没有确定有多少工作要做。)

    【讨论】:

    • 如果您不希望在行首出现微调器(或百分比或其他内容),请使用退格符 \b 而不是回车。
    • 太棒了 :) 这正是我想要的。
    • FWIW,我从 SQLite 的创建者那里得到了这个技巧……
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多