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

2024-01-23

我在用着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 https://github.com/tqdm/tqdm#writing-messages方法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]

另一方面,还有这个允许静默这些功能的解决方案 https://stackoverflow.com/a/2829036/3434933通过相当优雅地重定向sys.stdout进入虚空。 这对于使函数静音非常有效。

由于我想在不破坏进度条的情况下显示来自这些函数的消息,因此我尝试通过重定向将这两种解决方案合并为一个sys.stdout to tqdm.write()反过来,让tqdm.write()写信给old 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="") inside DummyFile.write()创建与第一个输出相同的结果,但仍然混乱。

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

我缺少什么?


重定向sys.stdout总是很棘手,当两个应用程序同时处理它时,它就变成了一场噩梦。

这里的技巧是tqdm默认情况下打印到sys.stderr, not sys.stdout。通常情况下,tqdm对于这两个特殊通道有一个反混淆策略,但是由于您正在重定向sys.stdout, tqdm由于文件句柄发生变化而感到困惑。

因此,您只需要明确指定file=sys.stdout to 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=True in tqdm.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过 tqdm.write() 重定向 python 脚本中的打印命令 的相关文章

随机推荐

  • 组合 Spark Dataframe 中链接在一起的行

    我有一个数据框 其行通过各种合并相互连接 到目前为止 我已经将 DF 转换为下面的格式 我在其中执行了 groupBy Merge To 并将它们收集到一个数组中 然后将其连接回我的原始 DF 看起来像这样 df1 Ref Merge To
  • Android IAB:“刷新库存时出错(查询商品价格)”开发者错误

    我一直在应用程序计费 v3 中设置 Android 使用IABHelper类 并遵循示例代码 http developer android com training in app billing index html由谷歌提供 我在购买过程
  • .NET TimeZone.CurrentTimeZone.GetDaylightChanges 返回错误的 2005 年 DST

    我使用以下代码显示 2005 年至 2035 年之间的夏令时 2005 年 这page http www timeanddate com time dst 2005 html显示 DST 为 4 月 3 日至 10 月 30 日之间 但 G
  • iOS 7,使用默认的 InteractivePopGestureRecognizer 快速向后滑动时损坏 UINavigationBar

    我有一个问题一直困扰着 但我不知道为什么会发生 如果我将细节控制器推入堆栈 然后使用默认左边缘快速向后滑动interactivePopGestureRecognizer 我的父 根视图控制器的UINavigationBar看起来损坏了或者什
  • Android 视频多次播放后停止播放错误 1、2147483648

    好吧 这有点令人沮丧 我已经搜索了 Stack 但似乎没有一个答案有帮助 我有一个 Android 应用程序 可以循环显示屏幕上的不同内容 在某一时刻 它会播放一个视频 同一个视频 从同一个位置加载 经过随机次数的播放后 它决定停止播放视频
  • MPMoviePlayerController - 加载电影时捕获网络错误

    有没有办法捕获异常 特别是网络错误 没有可用的连接 当使用 MPMoviePlayerController 时 我特别担心一旦播放器的实例被初始化initWithURL 您无法知道电影加载是否由于某种原因失败 我已经查看了可用的文档并意识到
  • SwiftUI LazyHGrid 动态行之间的空间

    您能否建议如何在网格中拥有动态的行数 我有 5 个单词 这些单词的宽度可能不同 这个想法是让它们彼此相邻显示 如果没有足够的空间 gt 移动到下一行 我目前正在使用这个 var rows GridItem init adaptive min
  • 为什么 JavaScript 的 getElementsByClassName 提供一个不是数组的对象?

    我正在尝试使用 JavaScript 不使用 jQuery 获取页面上具有特定类名的所有元素的列表 因此 我使用 getElementsByClassName 函数 如下所示 var expand buttons document getE
  • 使用 clang API 打印参数的类型 (ParmVarDecl)

    我需要使用 clang API 打印 C 源文件中参数的类型 如果我有 clang 中的参数表示 ParmVarDecl param 我可以使用打印参数的名称param gt getNameAsString 我需要一个方法param gt
  • 如何向 boto (Amazon S3) 中的密钥添加标签?

    我正在尝试标记已上传到 S3 的密钥 在下面的内容中 我只是从字符串创建一个文件 一旦我有了密钥 我不知道如何标记文件 我尝试过 Tag 和 TagSet from boto s3 bucket import Bucket from bot
  • PHP 将所有对象属性复制到此

    我有一个 PHP 类型的对象MyObject myObject instanceof MyObject 现在 在class MyObject 有一个非静态函数 在那里 我使用对 我 的引用 例如 this 但我那里还有另一个对象 是否有可能
  • 使用 mod_rewrite 进行语言重定向

    我有一个提供 7 种语言版本的网站 我希望仅当用户访问主页时才能根据浏览器语言重定向用户 这是为了增加有机流量的可用性 我需要此重定向仅适用于主页 因为该网站还会发送特定于每种语言的邮件 如果用户被重定向 它们将不起作用 此外 每种语言都是
  • 如何让长按电源键拒绝关机?

    在大多数较新的计算机上 您可以通过按住电源按钮几秒钟来硬关闭 但我想完全阻止这种情况发生 您可以阻止一些软事件 例如 Windows 控制面板中的睡眠 挂起 休眠和 按电源按钮 事件 您还可以使用一些 Win32 和 WDI 编程来捕获和处
  • __init__() 得到意外的关键字参数 'y'

    我正在阅读 绝对初学者的 Python 编程 一书 并决定通过制作自己的游戏来测试我的一些技能 这个游戏基本上是 不要被飞行的尖刺击中 我遇到了一个问题 使用此代码运行时 class Player games Sprite The play
  • Manifest 文件的用途是什么

    https docs oracle com javase tutorial deployment jar manifestindex html https docs oracle com javase tutorial deployment
  • 枚举所有打开的连接

    是否可以使用 NET枚举当前进程的所有打开的连接 与 netstat 工具执行此操作的方式类似 您可以使用IPGlobalProperties http msdn microsoft com en us library system net
  • 验证 React Native 中的 Style 属性类型

    我有一个组件 它的属性包含子组件的西林 我想确保propTypes正确验证它的类型 我可以从 React Native 代码中得知它有一个ViewStylePropTypes https github com facebook react
  • 如何将 DLL 链接到我的项目?错误 LNK2019:无法解析的外部符号

    我有一个文件foo h有各种函数声明 所有这些功能都在一个文件中实现foo dll 但是 当我包含 h 文件并尝试使用任何函数时 我收到错误 bar obj error LNK2019 unresolved external symbol
  • 替换单词和字符串 pandas

    dataframe pd DataFrame Date This 1A1619 person BL171111 the A 1 24 dont Z112 but NOT 1 22 2001 mix 1A25629Q88 or A13B ok
  • 通过 tqdm.write() 重定向 python 脚本中的打印命令

    我在用着tqdm在 Python 中显示脚本中的控制台进度条 但是 我必须调用函数print消息也发送到控制台 我无法更改 一般来说 在控制台中显示进度条时写入控制台会弄乱显示 如下所示 from time import sleep fro