Python上下文管理器

来源:千锋教育
发布时间:2023-11-07 04:07:19
分享

本节严格意义上并非新的重定向方式,而是利用Pyhton上下文管理器优化上节的代码实现。借助于上下文管理器语法,可不必向重定向使用者暴露sys.stdout。

首先考虑输出抑制,基于上下文管理器语法实现如下:

importsys,cStringIO,contextlib

classDummyFile:

defwrite(self,outStr):pass

@contextlib.contextmanager

defMuteStdout():

savedStdout=sys.stdout

sys.stdout=cStringIO.StringIO()#DummyFile()

try:

yield

exceptException:#捕获到错误时,屏显被抑制的输出(该处理并非必需)

content,sys.stdout=sys.stdout,savedStdout

printcontent.getvalue()#;raise

#finally:

sys.stdout=savedStdout

使用示例如下:

withMuteStdout():

print"I'llshowupwhenisexecuted!"#不屏显不写入

raise#屏显上句

print"I'mhidingmyselfsomewhere:)"#不屏显

再考虑更通用的输出重定向:

importos,sys

fromcontextlibimportcontextmanager

@contextmanager

defRedirectStdout(newStdout):

savedStdout,sys.stdout=sys.stdout,newStdout

try:

yield

finally:

sys.stdout=savedStdout

使用示例如下:

defGreeting():print'Hello,boss!'

withopen('out.txt',"w+")asfile:

print"I'mwritingtoyou..."#屏显

withRedirectStdout(file):

print'Ihopethisletterfindsyouwell!'#写入文件

print'Checkyourmailbox.'#屏显

withopen(os.devnull,"w+")asfile,RedirectStdout(file):

Greeting()#不屏显不写入

print'Ideserveapayraise:)'#不屏显不写入

print'DidyouhearwhatIsaid?'#屏显

可见,with内嵌块里的函数和print语句输出均被重定向。注意,上述示例不是线程安全的,主要适用于单线程。

当函数被频繁调用时,建议使用装饰器包装该函数。这样,仅需修改该函数定义,而无需在每次调用该函数时使用with语句包裹。示例如下:

importsys,cStringIO,functools

defMuteStdout(retCache=False):

defdecorator(func):

@functools.wraps(func)

defwrapper(*args,**kwargs):

savedStdout=sys.stdout

sys.stdout=cStringIO.StringIO()

try:

ret=func(*args,**kwargs)

ifretCache==True:

ret=sys.stdout.getvalue().strip()

finally:

sys.stdout=savedStdout

returnret

returnwrapper

returndecorator

若装饰器MuteStdout的参数retCache为真,外部调用func()函数时将返回该函数内部print输出的内容(可供屏显);若retCache为假,外部调用func()函数时将返回该函数的返回值(抑制输出)。

MuteStdout装饰器使用示例如下:

@MuteStdout(True)

defExclaim():print'Iamproudofmyself!'

@MuteStdout()

defMumble():print'Ilackconfidence...';return'sad'

printExclaim(),Exclaim.__name__#屏显'Iamproudofmyself!Exclaim'

printMumble(),Mumble.__name__#屏显'sadMumble'

在所有线程中,被装饰函数执行期间,sys.stdout都会被MuteStdout装饰器劫持。而且,函数一经装饰便无法移除装饰。因此,使用该装饰器时应慎重考虑场景。

接着,考虑创建RedirectStdout装饰器:

defRedirectStdout(newStdout=sys.stdout):

defdecorator(func):

defwrapper(*args,**kwargs):

savedStdout,sys.stdout=sys.stdout,newStdout

try:

returnfunc(*args,**kwargs)

finally:

sys.stdout=savedStdout

returnwrapper

returndecorator

使用示例如下:

file=open('out.txt',"w+")

@RedirectStdout(file)

defFunNoArg():print'Noargument.'

@RedirectStdout(file)

defFunOneArg(a):print'Oneargument:',a

defFunTwoArg(a,b):print'Twoarguments:%s,%s'%(a,b)

FunNoArg()#写文件'Noargument.'

FunOneArg(1984)#写文件'Oneargument:1984'

RedirectStdout()(FunTwoArg)(10,29)#屏显'Twoarguments:10,29'

printFunNoArg.__name__#屏显'wrapper'(应显示'FunNoArg')

file.close()

注意FunTwoArg()函数的定义和调用与其他函数的不同,这是两种等效的语法。此外,RedirectStdout装饰器的最内层函数wrapper()未使用"functools.wraps(func)"修饰,会丢失被装饰函数原有的特殊属性(如函数名、文档字符串等)。

以上内容为大家介绍了Python上下文管理器,希望对大家有所帮助,如果想要了解更多Python相关知识,请关注IT培训机构:千锋教育。

声明:本站部分稿件版权来源于网络,如有侵犯版权,请及时联系我们。

相关推荐

  • Python C代码统计工具代码的效果验证 为验证上篇文章的代码实现,建立lctest调试目录。该目录下包含line.c及和《为C函数自动添加跟踪语句》一文中的test.c文件。其中,line.c内容如下:#include/*{{{commen
  • python np.nonzero()函数 nonzero函数是numpy中用于得到数组array中非零元素的目录(位置)的函数。返回值为元组,两个值分别为两个维度,包含了相应维度上非零元素的目录值。只有a中非零元素才会有索引值,那些零值元素没
  • Python 分类技术 分类技术(或分类法)是一种根据输入数据建立分类模型的系统方法,分类法的例子包括决策分类法,基于规则的分类法,神经网络,支持向量机和朴素贝叶斯分类法。这些技术都使用一种学习算法(learningalgo
  • Python 决策树算法思想 决策树(decisiontree)是一个树结构(可以是二叉树或者非二叉树)。决策树分为分类树和回归树两种,分类树对离散变量做决策树,回归树对连续变量做决策树。其中每个非叶节点表示一个特征属性上的测试,
  • Python 决策树的生成算法介绍 划分数据集的最大原则是:使无序的数据变的有序。如果一个训练数据中有20个特征,那么选取哪个做划分依据?这就必须采用量化的方法来判断,量化划分方法有多重,其中一项就是“信息论度量信息分类”。基于信息论的
  • Python C4.5算法 ID3算法的作者昆兰基于上面的不足,对ID3算法做了改进,这就是C4.5算法,也许你会问,为什么不叫ID4,ID5之类的名字呢?那是因为决策树当时太火爆了,它的ID3一出来,别人二次创新,很快就占了I