暂无分类
暂无标签
发布于2021-02-24 09:36 阅读(142) 评论(0) 点赞(3) 收藏(5)
0
1
2
3
4
5
class Test:
def __init__(self):
print("__init__")
def main(self):
print("main")
def __del__(self):
with open("test.txt", "w") as f:
f.write("hhhhh")
print("__del__")
t = Test()
t.main()
会报错 NameError: name ‘open’ is not defined
python2没有这个问题
情景: 我的需求是在对象销毁时, 要在文件中进行一个记录
解决: 使用 try...except...finally...
try: # 在Test类中移除open()函数, 实例化对象交由try
t = Test()
t.main()
except Exception as e:
print(e)
finally: # open()函数交由finally
with open("test.txt", "w") as f:
f.write("20201214")
在__del__中无法使用open()函数, 将open()转移到其它对象方法中, 最后在析构函数中关闭
class Test:
def __init__(self):
print("__init__")
def main(self):
print("main")
self.file = open("test.txt", "w")
def __del__(self):
self.file.write("helloworld")
print("__del__")
self.file.close()
t = Test()
t.main()
在百度和必应中搜寻无果, 果然还是google更加强大!
为解决这一问题, 我们可以首先导入atexit模块, 然后将析构操作写入另一个函数中, 最后用atexit.register来注册这个函数. 比如, 以上程序可以改写如下:
import atexit
class 存储代理:
def __init__(self):
atexit.register(self.cleanup)
print("开始")
def cleanup(self):
print("打开文件前")
with open("./测试.txt", "w") as 文件:
pass
print("打开文件后")
def __del__(self):
pass
代理 = 存储代理()
atexit 按注册的相反顺序执行这些函数; 例如注册A、B、C,在解释器终止时按顺序C,B,A运行。
Note:如果程序是非正常crash,或者通过os._exit()
退出,注册的退出函数将不会被调用。
atexit.register(func, *args, **kargs)
将func作为要在终止时执行的函数。任何要传递给func的可选参数必须作为参数传递给register()
。可以多次注册相同的函数和参数。
当程序退出的时候,按先进后出的顺序调用注册的函数。如果退出函数在执行过程中抛出了异常,atexit会打印异常的信息,并继续执行下一下回调,直到所有退出函数执行完毕,它会重新抛出最后接收到的异常。
一.通过装饰器使用atexit
from atexit import register
def main():
print('Do something.')
@register
def _atexit():
print('Done.')
if __name__ == '__main__':
main()
输出: Do something
Done
二.非装饰器方式
from atexit import register
def main():
print('main')
def goodbye(name, adjective):
print('Goodbye, %s, it was %s to meet you.' % (name, adjective))
register(goodbye, 'Donny', 'nice')
# register(goodbye, adjective='nice', name='Donny')
if __name__ == '__main__':
main()
输出: main
Goodbye, Donny, it was nice to meet you.
class Test:
def __init__(self):
print("__init__")
def __del__(self):
with open("xianshi.txt", "w") as f:
f.write("ffff")
t = Test()
del t
dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。
所以, 利用dir()函数, 我想探究在析构函数中到底减少了哪些方法和属性
class Test:
def __init__(self):
print(dir(__builtins__), len(dir(__builtins__)))
print("__init__")
def __del__(self):
print("---del---")
print(dir(__builtins__), len(dir(__builtins__)))
print("---del---")
with open("test.txt", "w") as f:
f.write("ffff")
t = Test()
# del t
结果分析: 在__init__(self)中, 内建属性和方法有153个, 然而在__del__中只有146个, 减少了7个
我使用集合经行相减后发现, 缺失的内建有
{'quit', 'license', 'credits', 'exit', 'help', 'open', 'copyright'}
在交互式的python中, 内建属性方法有154个
如果上述代码的第14行取消注释, 在析构函数中的内建属性和方法仍然有153个
######个人看法
如果 , 此时python内的资源还健全, 要是等到 , 它已经清理了一些资源,所以当执行到一些已清理的资源时便会报错class Iam(object):
def __init__(self):
print("I m born")
def __del__(self):
#"open" function still in __builtins__
f = open("memory_report.txt", "w")
f.write("He gone safe")
f.close()
def write_iam():
print("----")
i=Iam()
print("====")
if __name__ == '__main__':
write_iam()
print("Script Ends. Now to GC clean memory")
主体程序结束后才调用 Iam类__del__方法,而不是当 i超出 write_iam的作用域时就去立即调用__del__方法。
原理如下:
Python 采用的是 引用计数机制为主, 标记-清除和分代收集两种机制为辅的策略。 因此, 当 Python 在超出范围时不会清理它,只有当它的最后一次引用超出范围时, 才会将它清理掉。0
1
2
3
4
5
作者:83whjh
链接: https://www.pythonheidong.com/blog/article/852421/fb132a44ab549861c4b0/
来源: python黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
Copyright © 2018-2021 python黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-1
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!