当前位置: 首页 > 面试题库 >

通过tqdm.write()在python脚本中重定向打印命令

贺俊杰
2023-03-14
问题内容

tqdm在Python中使用脚本来显示控制台进度条。但是,我必须调用将print消息也发送到控制台且不能更改的函数。通常,在控制台中显示进度条时写入控制台会使显示混乱,如下所示:

from time import sleep
from tqdm import tqdm

def blabla():
  print "Foo blabla"

for k in tqdm(range(3)):
  blabla()
  sleep(.5)

这将创建输出:

0%|                                           | 0/3 [00:00<?, ?it/s]Foo
blabla
33%|###########6                       | 1/3 [00:00<00:01,  2.00it/s]Foo
blabla
67%|#######################3           | 2/3 [00:01<00:00,  2.00it/s]Foo
blabla
100%|###################################| 3/3 [00:01<00:00,  2.00it/s]

根据tqdm该方法的文档,tqdm.write()提供了一种在不中断显示的进度条的情况下将消息写入控制台的方法。因此,此代码段提供了正确的输出:

from time import sleep
from tqdm import tqdm

def blabla():
  tqdm.write("Foo blabla")

for k in tqdm(range(3)):
  blabla()
  sleep(.5)

看起来像这样:

Foo blabla
Foo blabla
Foo blabla
100%|###################################| 3/3 [00:01<00:00,  1.99it/s]

另一方面,存在这种[解决方案,该解决方案允许通过相当优雅地重定向sys.stdout到void中来使那些功能静音。这对于使功能静音非常有效。

由于我仍然希望显示这些功能的消息而又不破坏进度条,因此我尝试通过重定向sys.stdout
解决方案tqdm.write(),然后依次tqdm.write()写入
解决方案,将两种解决方案合并为一个sys.stdout。结果为代码段:

from time import sleep

import contextlib
import sys

from tqdm import tqdm

class DummyFile(object):
  file = None
  def __init__(self, file):
    self.file = file

  def write(self, x):
    tqdm.write(x, file=self.file)

@contextlib.contextmanager
def nostdout():
    save_stdout = sys.stdout
    sys.stdout = DummyFile(save_stdout)
    yield
    sys.stdout = save_stdout

def blabla():
  print "Foo blabla"

for k in tqdm(range(3)):
  with nostdout():
    blabla()
    sleep(.5)

但是,这实际上会像以前那样产生更加混乱的输出:

0%|                                           | 0/3 [00:00<?, ?it/s]Foo
blabla


33%|###########6                       | 1/3 [00:00<00:01,  2.00it/s]Foo
blabla


67%|#######################3           | 2/3 [00:01<00:00,  2.00it/s]Foo
blabla


100%|###################################| 3/3 [00:01<00:00,  2.00it/s]

仅供参考:tqdm.write(..., end="")内部调用DummyFile.write()产生的结果与仍然混乱的第一个输出相同。

我不明白为什么这行不通,因为tqdm.write()应该在写消息之前先清除进度条,然后再重写进度条。

我想念什么?


问题答案:

重定向sys.stdout总是很棘手,并且当两个应用程序同时纠缠在一起时,它将变成一场噩梦。

这里的窍门是tqdm默认情况下打印到sys.stderr,而不是sys.stdout。通常,tqdm对于这两个特殊通道具有反混合策略,但是由于您正在重定向sys.stdouttqdm因此由于文件句柄发生更改而感到困惑。

因此,您只需要显式指定file=sys.stdoutto即可tqdm使用:

from time import sleep

import contextlib
import sys

from tqdm import tqdm

class DummyFile(object):
  file = None
  def __init__(self, file):
    self.file = file

  def write(self, x):
    # Avoid print() second call (useless \n)
    if len(x.rstrip()) > 0:
        tqdm.write(x, file=self.file)

@contextlib.contextmanager
def nostdout():
    save_stdout = sys.stdout
    sys.stdout = DummyFile(sys.stdout)
    yield
    sys.stdout = save_stdout

def blabla():
  print("Foo blabla")

# tqdm call to sys.stdout must be done BEFORE stdout redirection
# and you need to specify sys.stdout, not sys.stderr (default)
for _ in tqdm(range(3), file=sys.stdout):
    with nostdout():
        blabla()
        sleep(.5)

print('Done!')

我还增加了一些技巧,让输出更好的(例如,没有无用的\n使用时print()end='')。

/编辑:其实好像你可以做stdout启动后重定向tqdm,您只需要指定dynamic_ncols=Truetqdm



 类似资料:
  • 问题内容: 我无法弄清楚在脚本开始时该做什么,例如在此Scikit示例中。 我一直在Google中寻找 Python文档字符串, 在功能中提供一些文档似乎很有用。但是我看不到脚本中间有什么作用。 问题答案: 在功能中提供一些文档似乎很有用 这是真的。除功能外,文档也可以在模块中提供。因此,如果您有一个像这样的文件: 您可以像这样访问其文档字符串: 现在,回到您的问题:做什么?简而言之:它输出模块文

  • 问题内容: 我有一个python脚本test.py: 在linux命令行上执行 返回: 然后执行 哪个返回 如何重定向输出使os.system调用在print语句之前打印? 问题答案: 当您输出到管道时,Python缓冲写入的输出,并在刷新,溢出,关闭后(程序退出时)输出。虽然它将缓冲打印调用,但系统调用输出将直接输出到stdout中,并且其输出将不会被缓冲。这就是为什么您会看到这样的优先级。为了

  • 问题内容: 我有一个Python脚本,它利用“打印”来打印到stdout。我最近通过Python Logger添加了日志记录,并希望通过日志记录使这些打印语句进入日志记录器(如果启用了日志记录)。我不想修改或删除这些打印语句。 我可以通过执行’log.info(“ some info msg”)’进行记录。我希望能够做这样的事情: 如果启用了日志记录,则应该像记录log.info(“ test”)

  • 我正试图用脚本方法安装一个模块,但我不知道如何用节点脚本语言安装,或者如果你有任何想法请与我分享。

  • 问题内容: 我正在编写一个python脚本,该脚本可以检查各种条件并相应地运行powershell脚本,以帮助我自动完成从Windows XP到Windows 7的迁移。powershell脚本提供了自己的输出,可让用户了解发生的情况。我想获取powershell脚本的输出并将其打印为python脚本的输出。我环顾了一些问题,这些问题似乎想做同样的事情,但似乎对我没有帮助。最初我尝试使用 如此处的

  • 问题内容: 我正在尝试使用Linux crontab执行python脚本。我想每10分钟运行一次此脚本。 我找到了很多解决方案,但都无济于事。例如:在/etc/cron.d中编辑anacron或使用。我将此行放在文件的末尾,但它没有任何改变。我需要重启任何服务吗? 我必须编辑哪个文件来配置它? 提前致谢 这是脚本。 问题答案: 只需使用并按照此处的教程操作即可。 请参阅第3点,以获取有关如何指定频