作为一个例子,我想创建一个函数暂时将stdout指向日志文件。
棘手的是,代码必须保留文件处理程序和std sav以便在重定向之后进行恢复,我在类类型中写入以保留这两个变量。
这里是完整代码:
class STDOUT2file:
def __init__(self,prefix='report@'):
now=dt.date.today()
repname=repnameprefix=prefix+now.strftime("%Y%m%d")+'.txt'
count=0
while os.path.isfile(repname):
count+=1
repname=repnameprefix+(".%02d" %(count))
self.sav=sys.stdout
f=open(repname,'w')
sys.stdout=f
self.fname=repname
self.fhr=f
def off(self,msg=False):
sys.stdout=self.sav
self.fhr.close()
if msg:
print('output to:'+self.fname)
return
这是应用它的代码:
outbuf=STDOUT2file()
#codes to print out to stdout
outbuf.off(msg=True)
我想让它更干净,阅读'关闭'但它在第一次调用时返回一个函数,类似于类的分配类型。
我希望它像:
STDOUT2file('上&#39)
STDout2file('关闭',味精=真)
注意:重定向到stdout是我刚刚遇到的一个例子..我想知道的是,除了类类型之外的任何其他方式来制作像开/关类型这样的简单功能,其中涉及应该存储/检索状态变量最好让外面看不见。
答案 0 :(得分:3)
尝试使用上下文管理器。这个成语很常见,它包含在PEP that introduced context managers中(稍作修改):
from contextlib import contextmanager
@contextmanager
def redirect_stdout(new_stdout):
import sys
save_stdout = sys.stdout
sys.stdout = new_stdout
try:
yield
finally:
sys.stdout = save_stdout
或者,如果您愿意,可以使用__enter__
和__exit__
的基于类的版本:
class redirect_stdout:
"""Context manager for temporarily redirecting stdout to another file
docstring truncated
"""
def __init__(self, new_target):
self.new_target = new_target
def __enter__(self):
self.old_target = sys.stdout
sys.stdout = self.new_target
return self.new_target
def __exit__(self, exctype, excinst, exctb):
sys.stdout = self.old_target
Raymond Hettinger实际上是committed this to contextlib,它将作为contextlib.redirect_stdout()
包含在python 3.4中。
基本用法:
with open('somelogfile','a') as f:
with stdout_redirected(f):
print(something)
答案 1 :(得分:1)
是的,您可以将状态信息保存在函数中。只需将变量命名为functionname.something即可保存。例如:
def stdout2file(status, prefix='pre', msg=False):
import datetime as dt
import os
import sys
if not hasattr(stdout2file, 'sav'):
stdout2file.sav = None
if status == 'on':
if stdout2file.sav:
print('You have already triggered this once Ignoring this request.')
else:
now = dt.date.today()
repname = repnameprefix = prefix + now.strftime("%Y%m%d") + '.txt'
count = 0
while os.path.isfile(repname):
count += 1
repname = repnameprefix + (".%02d" %(count))
stdout2file.sav = sys.stdout
f = open(repname,'w')
sys.stdout = f
stdout2file.fhr = f
elif status == 'off':
if not stdout2file.sav:
print('Redirect is "off" already. Ignoring this request')
else:
sys.stdout = stdout2file.sav
stdout2file.fhr.close()
if msg:
print('output to:' + stdout2file.fhr.name)
stdout2file.sav = None
else:
print('Unrecognized request')
还可以将状态信息保存在可变关键字参数中,如下所示:
def stdout_toggle(prefix='pre', msg=False, _s=[None, None]):
import datetime as dt
import os
import sys
if _s[0] is None:
now = dt.date.today()
repname = repnameprefix = prefix + now.strftime("%Y%m%d") + '.txt'
count = 0
while os.path.isfile(repname):
count += 1
repname = repnameprefix + (".%02d" %(count))
f = open(repname,'w')
_s[:] = [sys.stdout, f]
sys.stdout = f
else:
sys.stdout = _s[0]
_s[1].close()
if msg:
print('output to:' + _s[1].name)
_s[:] = [None, None]
用户可以在没有任何参数的情况下调用上述内容,它将在打开和关闭之间的重定向之间切换。该函数通过关键字参数_s
记住当前状态,该参数是一个可变列表。
虽然有些人认为在函数调用之间保留mutable关键字参数是一个语言缺陷,但这与python哲学是一致的。这是有效的,因为关键字参数的默认值是在函数首次定义时分配的,即执行def
语句时,而不是在函数被调用时。因此,_s=[None, None]
在定义时被分配一次,之后可以自由变化。