如何传递或包装print命令stdout,以便print在每次调用时也调用一个函数?

问题描述

我正在尝试使长时间运行的工作自动化,并且我希望能够将所有控制台输出上传到另一个日志,例如CloudWatch Logs。在大多数情况下,这可以通过制作和使用自定义函数来代替打印来完成。但是MachineLearning中有一些功能,例如Model.summary()或进度条,它们可以在训练时自行输出到stdout。

我可以通过内部控制台日志在最后获得所有控制台输出。但是我需要的是实时上载stdout,无论谁调用。这样一来,通过查看Cloudwatch上的日志即可查看进度,而不必登录计算机并查看内部控制台日志。

基本上我需要的是:

From: call_to_stdout -> Console(and probably other stuff)
To:   call_to_stdout -> uploadLog() -> Console(and probably other stuff)

我需要的伪代码

class stdout_Passthru:
   def __init__(self,in_old_stdout):
      self.old_stdout = in_old_stdout

   def write(self,msg):
      self.old_stdout.write(msg)
      uploadLogToCloudwatch(msg)

def uploadLogToCloudwatch(msg):
   # Botocore stuff to upload to Cloudwatch

myPassthru = stdout_Passthru(sys.stdout)
sys.stdout = myPassthru

我已经尝试使用谷歌搜索,但是我得到的最好的是stringIO的东西,我可以在其中捕获stdout,但是直到调用函数结束并且可以再次插入代码后,我才能对其进行任何处理。我想每次使用stdout时都运行我的上传日志代码

这甚至可能吗? 请,谢谢。

编辑:有人建议将重定向/输出文件。问题在于,随着事物的输出,流/文件只写入/写入文件。我需要调用对stdout的每次调用都起作用的函数,这不是流。如果stdout每次刷新时都输出,那么进行函数调用也将很好。

解决方法

我解决了我的问题。某种隐藏在其他答案中。 此解决方案的最初问题是,在Jupyter Notebook中对其进行测试时,sys.stdout = myClass(s​​ys.stdout)会导致Jupyter……等待吗?不确定,但是它永远不会完成对段落的处理。

但是当我将其放入python文件并与python test.py一起运行时,它可以完美运行,并且符合预期。

从某种意义上讲,这使我可以通过打印调用进行传递,而每次打印调用都执行自己的功能。

def addLog(message):
    # my boto function to upload Cloudwatch logs

class sendToLog:
    def __init__(self,stream):
        self.stream = stream
    def write(self,o):
        self.stream.write(o)
        addLog(o)
        self.stream.flush()
    def writelines(self,o):
        self.stream.writelines(o)
        addLog(o)
        self.stream.flush()
    def __getattr__(self,attr):
        return getattr(self.stream,attr)

sys.stdout = sendToLog(sys.stdout)