管道控制台从特定函数输出到文件-python

管道控制台从特定函数输出到文件-python,python,file,console-output,Python,File,Console Output,我有一个无法编辑的函数,它将结果打印到控制台上。是否可以调用该函数,但在不更改该函数的内部代码的情况下将控制台输出通过管道传输到文件中 例如,我有: def somefunc(x): print "Hello World", x**x def pipeout(func, outfilename) with open('outfilename', 'w') as fout: # somehow pipes out the output... 我无法使用logger,因为我无法编

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

例如,我有:

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श威尼चhaudhary的解决方案,但我无法确定,除了第一个outputfile之外,其他文件都是空的,而且它会一次又一次地覆盖该文件:

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.\uu stdout\uuu

我不久前就有这种需要,而且:

您可以这样使用它:

with OutStreamCapture() as osc:
    somefunc(x)
然后是
osc.stdout
osc.stderr
这两个字符串分别包含函数放入stdout和stderr中的任何内容

可以将其修改为使用任意文件


注意这里我将在上下文管理器中缓存
sys.stdout
的当前值,而不是使用
sys.\uuuu stdout\uuu
进行恢复。这是因为在我们进入这个上下文时,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
更新:

>>> %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)

为什么你不能编辑这个函数。这是python,每个函数都在纯文本文件中。可能是一个库函数,需要在一些即将部署的项目中使用。当然你可以编辑它,但有时你不应该。是的,从逻辑上讲,我可以编辑这个函数,但它会在我和其他开发人员之间造成各种各样的复杂性,最好避免合并冲突,并为scrum meeting=@alvas不要在循环中一次又一次地将
somefunc
分配给新函数,使用不同的变量名或直接调用
redirect\u output(outputfilename)(somefunc)(i)
@alvas,并使用append模式
'a'
来防止数据的重新写入。但是,装饰器需要额外的间接级别,因为OP不能修改
somefunc
,我假设他也不能装饰它,所以他需要写一个装饰过的包装纸。在这种情况下,您最好放弃整个decorator,只做简单的包装。@JacobodeVera如果他们从模块导入函数,那么他们可以使用其他decorator表示法:
somefunc=redirect\u output('file.txt')(somefunc)
@aश威尼चhaudhary,我对decorator解决方案仍有问题,请参阅更新的问题。我从OutStreamCapture类中获得
属性错误:\uuuuu exit\uuuu
,这是因为py2.x默认情况下没有
\uu exit\uuuuu
?@alvas抱歉,用OutStreamCapture()作为osc:漏掉了括号
。请再试一次。