0

我正在寻找一种方法来替换或删除 python 的日志记录模块写入的最后一条消息。目标是在变量发生变化时记录它。如果变量再次更改,则应删除旧的日志消息并打印新的日志消息。

你好,

我正在将 pythons 的日志记录模块用于我目前正在从事的深度学习项目。由于某些 GPU 没有足够的内存来支持训练期间的默认批量大小,并且批量大小和可用于事先计算的实际内存使用量之间没有明显的联系,因此一旦发生运行时错误,我就会发现它,并且将批量大小减少一。这个过程可以重复很多次,我总是记录哪个批量大小不起作用,哪个将是下一个尝试。我不想拥有 10-30 条(或更多)这些消息,而是简单地删除最后一条并用新的替换它。

我已经查看了 python 日志记录文档,偶然发现了 LogRecord 对象,但是在尝试处理它时,似乎这个对象实际上并没有记录所有日志,而是在一个特定日志上保存了一些更多信息.

如果根本没有办法做到这一点,我将研究某种捆绑解决方案,如下所述:Python logging: bundle reoccurring messages

下面的代码显示了我要替换的日志消息。

非常感谢任何帮助。

training_not_successful = True
    while training_not_successful:
        try:
            model.run_training(global_settings['epochs'],
                               train_loader,
                               test_loader,
                               global_settings['checkpoint_output_path'],
                               model_name,
                               global_settings['best_net_criterion'])
            training_not_successful = False
        except MemoryError:
            logging.warning("Ran out of CUDA memory using batch size " + str(batch_size) +
                            ". Trying again with batch size " + str(batch_size-1))
            batch_size -= 1
            train_loader, test_loader = get_train_test_loaders(
                train_dataset_list,
                test_dataset_list,
                value_counts,
                batch_size
            )
4

1 回答 1

0

我相信(如果我错了,请纠正我)日志记录模块不允许抑制换行符,这意味着根本不可能做这样的事情。

可以通过打印来做到这一点:

import shutil

def display(variable, rewritable=False):
    columns, lines = shutil.get_terminal_size(fallback=(80, 20))
    text = str(variable)
    filled = text + ((columns - len(text)) * ' ')
    print(filled, end='\r' if rewritable else '\n')

if __name__ == "__main__":
    from random import random
    from time import sleep

    for i in range(10):
        display(f"x = {random()}", True)
        sleep(1)
    display(f"x = 0.0") # test if old value is overwritten completely
    display("Done!")

在linux上测试过这个,但它应该在任何地方都可以工作。(shutil.get_terminal_size功能)

这不是强制性的,但是当整行被覆盖而不是仅被更改的部分时非常好。

关键是字符\r- 它将光标返回到行尾,就是这样。现在您可以再次从前面开始书写,如果有其他内容则覆盖该行,这正是您想要的。

显示功能很简单,但我还是解释一下:

第一行获取终端大小,我们需要的是行的宽度,因此我们可以用空格填充文本并用空格填充整行,以完全覆盖前一行,无论它有什么。

然后我们将变量转换为字符串。

之后,这只是简单的数学运算,我们的字符串需要n字符,所以其余的应该是空格,所以我们width - n在最终字符串中添加空格,然后打印它——整行都被覆盖了。

rewritableflag 允许控制下次调用 display 时应该重写变量的时间。

虽然这不是你想要的,因为它不使用日志记录模块,因为没有办法(据我所知)让日志记录模块打印\r而不是\n,我认为这是一个足够好的替代品,如果它可以使用事实证明,您确实可以使用日志记录模块来做到这一点。

于 2019-08-03T12:59:30.477 回答