千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  技术干货  > Python上下文管理器

Python上下文管理器

来源:千锋教育
发布人:xqq
时间: 2023-11-07 19:37:35 1699357055

本节严格意义上并非新的重定向方式,而是利用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培训机构:千锋教育。

tags: python培训
声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。
10年以上业内强师集结,手把手带你蜕变精英
请您保持通讯畅通,专属学习老师24小时内将与您1V1沟通
免费领取
今日已有369人领取成功
刘同学 138****2860 刚刚成功领取
王同学 131****2015 刚刚成功领取
张同学 133****4652 刚刚成功领取
李同学 135****8607 刚刚成功领取
杨同学 132****5667 刚刚成功领取
岳同学 134****6652 刚刚成功领取
梁同学 157****2950 刚刚成功领取
刘同学 189****1015 刚刚成功领取
张同学 155****4678 刚刚成功领取
邹同学 139****2907 刚刚成功领取
董同学 138****2867 刚刚成功领取
周同学 136****3602 刚刚成功领取
相关推荐HOT