将特定函数的控制台输出管道传输到python中



我有一个无法编辑的函数,它会将结果打印到控制台上。是否可以调用该函数,但在不更改函数内部代码的情况下将控制台输出管道传输到文件中?

例如,我有:

def somefunc(x):
  print "Hello World", x**x
def pipeout(func, outfilename)
  with open('outfilename', 'w') as fout:
    # somehow pipes out the output...

我无法使用logger,因为我无法编辑somefunc()

我尝试过@Aशwiniचhaudhary的解决方案,但我不能。除了第一个输出文件之外,其他文件都是空的,而且它一次又一次地覆盖该文件。:

def redirect_output(file_name):
  def decorator(func):
    def wrapper(*args):
      with open(file_name, 'w') as f:
        original_stdout = sys.stdout
        sys.stdout = f
        func(*args)
      sys.stdout = original_stdout
    return wrapper
  return decorator
def somefunc(x):
  print x*x
xs = [1,2,3,4]
for i in xs:
  outputfilename = 'results/'+str(i)
  somefunc = redirect_output(outputfilename)(somefunc)
  somefunc(i)

是的,您可以将sys.stdout的值设置为另一个具有写访问权限的打开文件。然后您可以使用sys.__stdout__ 将其设置回原位

我不久前就有这种需求,并做了一个上下文管理器:

import sys                                                                                                                          
from StringIO import StringIO 
class OutStreamCapture(object):
    """
    A context manager to replace stdout and stderr with StringIO objects and
    cache all output.
    """
    def __init__(self):
        self._stdout = None
        self._stderr = None
        self.stdout = None
        self.stderr = None
    def __enter__(self):
        self._stdout = sys.stdout
        self._stderr = sys.stderr
        sys.stdout = StringIO()
        sys.stderr = StringIO()
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        Restore original values of stderr and stdout.
        The captured contents are stored as strings in the stdout and stderr
        members.
        """
        self.stdout = sys.stdout.getvalue()
        self.stderr = sys.stderr.getvalue()
        sys.stdout = self._stdout
        sys.stderr = self._stderr

你可以这样使用它:

with OutStreamCapture() as osc:
    somefunc(x)

然后是osc.stdoutosc.stderr,您有两个字符串,其中包含函数分别放入stdout和stderr中的任何内容。

这可以修改为使用任意文件。

注意这里我在上下文管理器中缓存sys.stdout的当前值,而不是使用sys.__stdout__进行恢复。这是因为在我们进入这个上下文的时候,stdout可能已经被重定向了,我们想把它放回原来的样子。

当函数被调用时,您可以使用装饰器将sys.stdout重定向到文件对象,然后将其恢复到原始STDOUT。

import sys
def redirect_output(file_name):
    def decorator(func):
        def wrapper(*args):
            with open(file_name, 'w') as f:
                original_stdout = sys.stdout
                sys.stdout = f
                func(*args)
            sys.stdout = original_stdout
        return wrapper
    return decorator
@redirect_output('file.txt')
def somefunc(x):
  print "Hello World", x**x

somefunc(2)
print 'Hello to console.'

输出:

>>> %run so.py
Hello to console.
>>> !cat file.txt
Hello World 4

更新:

最新代码的工作版本:

for i in xs:
  outputfilename = 'results/'+str(i)
  new_func = redirect_output(outputfilename)(somefunc)
  #or call it directly
  #redirect_output(outputfilename)(somefunc)(i)
  new_func(i)

相关内容

  • 没有找到相关文章

最新更新