【问题标题】:Python: Writing a progress bar to a filePython:将进度条写入文件
【发布时间】:2016-03-31 19:02:26
【问题描述】:

我有一个 python 脚本,作为它的一部分,它运行一个 perl 脚本。我正在使用subprocess 模块执行和捕获stdoutstderr;伪代码是:

import subprocess as sp
import sys
perl_script='/usr/.../foo.pl'
p = sp.Popen(perl_script,stdout=sp.PIPE,stderr=sp.PIPE)
fname='test.log'
shell_out=True
text = ''
with open(fname, 'w') as log:
    while True:
        data = p.stdout.read(1)
        if data == '' and p.poll() != None:
            break
        if data != '':
            if shell_out is True:
                sys.stdout.write(data)
                sys.stdout.flush()
            log.write(data)
    p.stdout.close()

对于循环的每次迭代,数据似乎是单个字符串字符。

我遇到的问题是这个 perl 脚本显示了一个被它覆盖的进度条;类似:

[#####.....] 50%

每 5% 更新一次。因此,我写入的日志文件最终会包含以下内容:

[#.........] 5% [##........] 10% [###.......] 15%

等等。

有没有一种方法或方式可以让我覆盖日志文件中的前一行,或者我唯一的选择是捕获所有文本,尝试修改它,然后将其写入日志文件?

编辑:我认为我给出的示例的简单性质可能无法说明整个故事。这个 perl 脚本有多个进度条(每个任务一个)并输出我想要记录的附加信息。更详细的例子是:

NOTICE: one or more of things did stuff and you probably want to take note of it
writing the foo file . . .
    writing things . . .                             [####################] 100%
    writing stuff . . .                              [####################] 100%
    writing items . . .                              [####################] 100%
done
creating other files...
done

请记住,上面的输出是一个与这个 perl 脚本的标准输出特性相匹配的示例,并且实际输出(我无法发布)大约是 100 行左右。

最后,感谢格式化帮助:)

编辑#2:当stdout 被捕获时,我已经放弃尝试写入日志文件,而是将stdout 存储在一个变量中,并在脚本完成后写入日志文件。剩下的唯一问题是如何正确格式化字符串,以便正确写入日志文件。更新后的伪代码为:

import subprocess as sp
import sys
tg_post='/usr/.../foo.pl'
p = sp.Popen(tg_post,stdout=sp.PIPE)
text = ''
fname='test.log'
shell_out=True
while True:
    data = p.stdout.read(1)
    if data == '' and p.poll() != None:
        break
    if data != '':
        if shell_out is True:
            sys.stdout.write(data)
            sys.stdout.flush()
        text += data        
p.stdout.close()
text = text.split('\r')
with open(fname, 'w') as log:
    log.write(text)

目前,此代码为每个状态栏的每个百分比生成一行。我想我可以遍历文本中的每个索引(拆分后)并删除有# 而不是100% 的索引,但我希望有更强大的东西。如果我print text(拆分后),我会在屏幕上得到我想要的。我知道可以使用print 写入文件,但我想避免这种情况(我相信不再使用该方法)。

【问题讨论】:

  • 为什么要覆盖日志文件中的行?
  • @nathan.meadows - 如果我不覆盖日志文件中的行,那么它不是一个易于阅读的 ~100 行文件,而是一个 ~50 行文件,其中一些行大约有 1600 个字符。

标签: python


【解决方案1】:

您可以在 while 循环之外定义数据,并在最后将最后的状态写入文件。这样它只会将数据保存的最后状态更新写入文件,这样可以避免不断覆盖文件的最后状态。

import subprocess as sp
import sys
perl_script='/usr/.../foo.pl'
p = sp.Popen(perl_script,stdout=sp.PIPE,stderr=sp.PIPE)
fname='test.log'
shell_out=True
text = ''
data = ''

while True:
    data = p.stdout.read(1)
    if data == '' and p.poll() != None:
        break
    if data != '':
        if shell_out is True:
            sys.stdout.write(data)
            sys.stdout.flush()
    p.stdout.close()
with open(fname, 'w') as log:
    log.write(data)

【讨论】:

  • 问题是数据总是单个字符,因此对于这个 perl 脚本的细节,这将导致日志文件只是 \n。我可以在每次迭代时附加一个data,然后在循环之后修改data,但我希望能够在获得stdout时写入日志文件。
  • 你想在做的时候做的原因是什么?在这种情况下,.strip() 可能会派上用场
  • 我想得越多,我认为写日志文件的重要性就越低,因为stdout 被捕获。鉴于此,唯一的问题是如何格式化文本以删除所有将被覆盖的行。我会相应地更新我原来的帖子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-30
  • 2015-08-22
  • 1970-01-01
  • 2013-01-07
  • 1970-01-01
相关资源
最近更新 更多