【问题标题】:How to capture print output of another module?如何捕获另一个模块的打印输出?
【发布时间】:2023-03-06 23:50:01
【问题描述】:

我想知道这在 python 中是否可行:

# module1
def test():
    print('hey')

# module2
import module1

module1.test() # prints to stdout

如果不修改module1,有什么方法可以将其包装在module2 中,以便我可以捕获 print('hey') 在变量中?除了将module1 作为脚本运行?

【问题讨论】:

标签: python stdout


【解决方案1】:

将 ftplib 调试输出发送到日志记录模块

基于jimmy kumar ahalpara 回答所采用的方法,我能够将ftplib 的调试输出捕获到logging 中。 ftplib 出现在日志模块之前,它使用print 来发出调试消息。

我尝试将打印功能重新分配给记录方法,但我无法让它工作。下面的代码对我有用。

我应该认为这也适用于其他模块,但不同模块的输出之间不会有任何粒度,因为它会将发送到 stdout 的所有内容捕获到同一个记录器。

# convenience class to redirect stdout to logging
class SendToLog:

    def __init__(self, logging_method):

        self.logger = logging
_method
    def write(self, o):

        if str(o).strip():  #  ignore empty lines
            self.logger(str(o))


import logging
import sys

# code to initialise logging output and handlers ...
# ...

# get logger for ftplib and redirect it's print output to our log
ftp_logger = logging.getLogger('ftplib')
# note: logging's debug method is passed to the class, the instance then calls this method
sys.stdout = SendToLog(ftp_logger.debug)

# code to do stuff with ftplib ...
# remember to set ftplib's debug level > 0 or there will be no output
# FTP.set_debuglevel(1)
# ...

# important to finalise logging and restore stdout
logging.shutdown()
sys.stdout = sys.__stdout__

【讨论】:

    【解决方案2】:

    没有必要使用另一个模块,只需要具有写入属性的类对象,一个输入,您可以将其保存在另一个变量中。为 ecample

    类:

    class ExClass:
        def __init__(self):
            self.st = ''
        def write(self, o): #here o is the output that goes to stdout
            self.st += str(o)
    

    主程序:

    import sys
    stdout_ = sys.stdout
    var = ExClass()
    sys.stdout = var
    
    print("Hello") # these will not be pronted 
    print("Hello2") # instead will be written in var.st
    
    sys.stdout = stdout_
    
    print(var.st) 
    

    输出将是

    Hello
    Hello2
    

    【讨论】:

      【解决方案3】:

      我不想负责修改sys.stdout,然后将其恢复到以前的值。上述答案没有任何finally: 子句,将其集成到其他重要代码中可能会很危险。

      https://docs.python.org/3/library/contextlib.html

      import contextlib, io
      
      f = io.StringIO()
      with contextlib.redirect_stdout(f):
          module1.test()
      output = f.getvalue()
      

      您可能想要变量output,即<class 'str'>,并带有重定向的标准输出。

      注意:此代码是从官方文档中提取的,经过了一些简单的修改(但经过测试)。这个答案的另一个版本已经在这里给出了一个大部分重复的问题:https://stackoverflow.com/a/22434594/1092940

      我将答案留在这里,因为它比 IMO 的其他解决方案要好得多。

      【讨论】:

        【解决方案4】:

        对于 Python 3:

        # redirect sys.stdout to a buffer
        import sys, io
        stdout = sys.stdout
        sys.stdout = io.StringIO()
        
        # call module that calls print()
        import module1
        module1.test()
        
        # get output and restore sys.stdout
        output = sys.stdout.getvalue()
        sys.stdout = stdout
        
        print(output)
        

        【讨论】:

          【解决方案5】:

          是的,你只需要将stdout重定向到一个符合stdout接口的内存缓冲区,你可以用StringIO来做。这在 2.7 中适用于我:

          import sys
          import cStringIO
          
          stdout_ = sys.stdout #Keep track of the previous value.
          stream = cStringIO.StringIO()
          sys.stdout = stream
          print "hello" # Here you can do whatever you want, import module1, call test
          sys.stdout = stdout_ # restore the previous stdout.
          variable = stream.getvalue()  # This will get the "hello" string inside the variable
          

          【讨论】:

          • 这种方式sys.stdout.encoding会有所不同(在标准输出改变后),stdout提供的不仅仅是write
          【解决方案6】:

          是的,你可以。您需要控制sys.stdout。像这样的:

          import sys
          
          stdout_ = sys.stdout #Keep track of the previous value.
          sys.stdout = open('myoutputfile.txt', 'w') # Something here that provides a write method.
          # calls to print, ie import module1
          sys.stdout = stdout_ # restore the previous stdout.
          

          【讨论】:

          • 您不需要第一行 - 您可以通过将最后一行替换为:sys.stdout = sys.__stdout__ 来恢复默认标准输出
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多