Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 临时重定向stdout/stderr_Python_Redirect_Stdout_Stderr - Fatal编程技术网

Python 临时重定向stdout/stderr

Python 临时重定向stdout/stderr,python,redirect,stdout,stderr,Python,Redirect,Stdout,Stderr,是否可以在Python中临时重定向stdout/stderr(即在方法期间) 编辑: 当前解决方案的问题(我起初记得,但后来忘记了)是它们没有重定向;相反,它们只是完全替换了流。因此,如果由于任何原因(例如,因为流作为参数传递给某个对象),某个方法具有一个变量的本地副本,则该方法将不起作用 有什么解决办法吗?我不知道临时重定向是什么意思。但是,您可以像这样重新分配流并将其重置回来 temp = sys.stdout sys.stdout = sys.stderr sys.stderr = tem

是否可以在Python中临时重定向stdout/stderr(即在方法期间)

编辑: 当前解决方案的问题(我起初记得,但后来忘记了)是它们没有重定向;相反,它们只是完全替换了流。因此,如果由于任何原因(例如,因为流作为参数传递给某个对象),某个方法具有一个变量的本地副本,则该方法将不起作用


有什么解决办法吗?

我不知道临时重定向是什么意思。但是,您可以像这样重新分配流并将其重置回来

temp = sys.stdout
sys.stdout = sys.stderr
sys.stderr = temp
也可以像这样在打印stmts中写入sys.stderr

 print >> sys.stderr, "Error in atexit._run_exitfuncs:"

常规打印将发送到标准输出。

可以使用以下装饰器:

import sys

def redirect_stderr_stdout(stderr=sys.stderr, stdout=sys.stdout):
    def wrap(f):
        def newf(*args, **kwargs):
            old_stderr, old_stdout = sys.stderr, sys.stdout
            sys.stderr = stderr
            sys.stdout = stdout
            try:
                return f(*args, **kwargs)
            finally:
                sys.stderr, sys.stdout = old_stderr, old_stdout

        return newf
    return wrap
用作:

@redirect_stderr_stdout(some_logging_stream, the_console):
def fun(...):
    # whatever
或者,如果您不想修改
fun
的源代码,请直接将其作为

redirect_stderr_stdout(some_logging_stream, the_console)(fun)

但请注意,这不是线程安全的。

您也可以将重定向逻辑放在contextmanager中

import os
import sys

class RedirectStdStreams(object):
    def __init__(self, stdout=None, stderr=None):
        self._stdout = stdout or sys.stdout
        self._stderr = stderr or sys.stderr

    def __enter__(self):
        self.old_stdout, self.old_stderr = sys.stdout, sys.stderr
        self.old_stdout.flush(); self.old_stderr.flush()
        sys.stdout, sys.stderr = self._stdout, self._stderr

    def __exit__(self, exc_type, exc_value, traceback):
        self._stdout.flush(); self._stderr.flush()
        sys.stdout = self.old_stdout
        sys.stderr = self.old_stderr

if __name__ == '__main__':

    devnull = open(os.devnull, 'w')
    print('Fubar')

    with RedirectStdStreams(stdout=devnull, stderr=devnull):
        print("You'll never see me")

    print("I'm back!")

这是一个我觉得有用的上下文管理器。它的好处是,您可以将它与
with
语句一起使用,它还可以处理子进程的重定向

导入上下文库
@contextlib.contextmanager
def stdchannel_已重定向(stdchannel,dest_文件名):
"""
用于临时重定向stdout或stderr的上下文管理器
例如。:
重定向stdchannel_时(sys.stderr,os.devnull):
...
"""
尝试:
oldstdchannel=os.dup(stdchannel.fileno())
dest_文件=打开(dest_文件名'w')
os.dup2(dest_file.fileno(),stdchannel.fileno())
产量
最后:
如果oldstdchannel不是None:
os.dup2(oldstdchannel,stdcchannel.fileno())
如果dest_文件不是None:
dest_file.close()文件
我为什么创建这个的背景是。

向我们展示了一种更好的方法[1]:

import sys
with open(filepath + filename, "w") as f: #replace filepath & filename
    with f as sys.stdout:
        print("print this to file")   #will be written to filename & -path
使用块后,将重置sys.stdout


[1] :

要解决某些函数可能已将
sys.stdout
流缓存为局部变量,因此替换全局
sys.stdout
在该函数内不起作用的问题,可以在文件描述符级别(
sys.stdout.fileno()
)重定向,例如:

将sys.stdout.fileno()的所有输出重定向到给定的文件名、文件对象或文件描述符(
os.devnull


.

我们将在python3中使用和函数的
PHP
语法,并将输入重定向到文件中

输出存储在文件中,也可以使用任何类型的流

from functools import partial
output_buffer = None
print_orig = print
def ob_start(fname="print.txt"):
    global print
    global output_buffer
    print = partial(print_orig, file=output_buffer)
    output_buffer = open(fname, 'w')
def ob_end():
    global output_buffer
    close(output_buffer)
    print = print_orig
def ob_get_contents(fname="print.txt"):
    return open(fname, 'r').read()
用法:

print ("Hi John")
ob_start()
print ("Hi John")
ob_end()
print (ob_get_contents().replace("Hi", "Bye"))
将打印

嗨,约翰 再见,约翰


从python 3.4开始,有一个上下文管理器:

要使标准输出完全静音,请执行以下操作:

from contextlib import redirect_stdout

with redirect_stdout(None):
    # do stuff...


看和看。在Python3.5中是新的。

我想我可以包装一个
try finally
;看起来会管用的,虽然没有我想要的那么漂亮。感谢+1此示例适用于我们这些坚持使用python 2.2的人。谢谢你不需要临时工。sys.\uu stderr\uuuuuuu始终是正确的对象。+1对于我在Python中看到的这个问题的最干净、最简单的解决方案,您不需要
temp
变量。您可以调用sys.stdout,sys.stderr=sys.stderr,sys.stdout+1似乎就是我需要的。只是好奇,你为什么要做一个
except:raise
。顺便说一句,我重写了整件事。;我第一次总是错误地理解decorators中的嵌套级别,但现在它实际上可以工作了。你知道,我注意到一个问题:如果程序缓存了流对象(例如,将它们作为参数传递给接受流的函数),该怎么办?那么这就行不通了有没有办法重定向流本身,而不是用新的流替换它们?@Mehrdad:然后你可以做一些低级的文件描述符魔术,或者甚至在执行所需代码之前,在子级中分叉并重定向流,并通过管道返回结果。恐怕这里没有什么灵丹妙药。将return wrap(f)改为return wrap预定向stdout/stderr并不少见(或者至少并非闻所未闻)——这里的答案很好地解释了这个过程。@TokenMacGuy:虽然你永远不应该编写将输出连接到
stderr
stdout
的库代码,您不能总是避免使用这种代码。@Mehrdad在导入第三方代码之前,请尝试替换sys.\u stdout\uuuumodules@Rob:我想你错过了我标题中的第二个字。:-)@梅尔达德:不。将代码早期的sys.\uu stdout\uuuu替换为您自己的流式对象(即实现
.write()
)。对sys.stdout的所有引用都指向它。将其代理到可变流,默认为标准输出。然后,您应该能够随意切换代理流。我没有试过这个;我想得很清楚,-1--带有的
将不会恢复初始的
sys.stdout
。如果您试图在使用
块的
之后打印某些内容,您将收到一个
值错误:对关闭的文件执行I/O操作。
。您应该用
删除第二个
,并将一个
sys.stdout=sys.\uuu stdout\uuuu
放在第一个
块的末尾。此答案将替换
sys.stdout
sys.stderr
,而不是在编辑的问题版本中按OP要求重定向它们。请参阅。@RobCowie:Style问题:您之所以将
self.\u stdout
“受保护”(在Python意义上)与
self.\u stdout
“私有”(在Python意义上)进行比较,是有原因的吗?我似乎从来没有创建过私有的双下划线属性。我还没有找到一种情况来证明这一点。@kevinarpe-在
x.\u-bar
x.\u-bar
之间没有什么区别,只是
x.\u-bar
更难理解,因为名称被弄错了。事实上,这并不能使这个变量
from contextlib import redirect_stdout

with open('yourfile.txt', 'w') as f:
    with redirect_stdout(f):
        # do stuff...
from contextlib import redirect_stdout

with redirect_stdout(None):
    # do stuff...