sys.getrefcount 继续
我明白了引用计数的概念。
所以当我执行“del astrd”时,引用计数降到零,astrd就会被垃圾回收器收走吗?
这是我写的示例代码。这些代码是我在昨天提问后开发的:链接文本
one.py:
def abc():
print "Hello"
print "123"
print '345'
two.py:
import one
#reload(one)
#def defg():
one.abc()
three.py:
import os,sys,gc
from time import sleep
import two
#reload(two)
#two.defg()
sleep(20)
directory = os.listdir('.')
for filename in directory:
if filename[-3:] == 'pyc':
print '- ' + filename
print sys.getrefcount(filename)
file_name = os.path.splitext (filename)[0]
del file_name # remove the local reference
del sys.modules[os.path.splitext (filename)[0]] # removes import
gc.collect() # garbage collect
#del sys.modules[filename]
#del filename
#os.remove(filename)
我在three.py中做的对吗?
有没有多余的步骤?如果有,为什么?
请帮我解决这个问题。
3 个回答
你能简单介绍一下你在做什么吗?
一般来说,使用 del
来删除变量的情况不多,主要是为了清理那些你不想让别人看到的东西。比如你在代码里用 del file_name
或者运行 gc.collect()
,我不太明白你这样做的原因。(不过 del sys.modules[filename]
是可以的,因为那是 del
的另一种用法。)
对于一些对象,比如字符串(像 file_name
),你不需要关心它们具体什么时候被清理。等你的函数结束后,这些变量自然就会被清理掉,直到那时它们不会造成任何问题。所以,手动调用 del
只会让你的代码看起来更乱。
如果是一些需要立即清理的对象,比如打开的文件或者锁,你就不应该依赖垃圾回收器了,因为它并不能保证会立刻清理这些对象。在标准的C语言实现的Python中,它可能会这样做,但在Jython或IronPython中就不一定了。所以,最好是通过调用 close
或者使用新的 with
语法来手动清理这些对象。
另外一个可能的原因是你分配了大量内存,想在变量自然消失之前,提前告诉系统你已经用完了这些内存。
不过,你的例子似乎不符合这两种情况,所以我不太明白你为什么要手动调用垃圾回收器。
它有一个机会在下一个垃圾回收(GC)运行时被清理掉。
我认为,当引用计数(refcount)变为零时,内存会自动释放。垃圾回收(GC)并不参与这个过程。
Python的垃圾回收是可选的,只有在有无法访问的对象并且这些对象之间有引用循环时才会使用。实际上,如果你确定你的程序不会产生引用循环,可以调用 gc.disable()
来关闭垃圾回收。
关于最初的问题:
- 当你执行
del astrd
时,你只是把astrd这个名字从本地命名空间中移除了,也就是把它和某个对象的联系断开了(无论astrd原本指向什么)。 - 如果这导致引用计数变为零,那么这个对象占用的内存就会被释放。
- 所以,
del
并不是删除对象,而是解除引用的绑定。对象的删除是一个副作用,只有在解除引用后引用计数变为零时才会发生。
需要注意的是,上述内容仅适用于CPython。Jython和IronPython使用的是JVM/CLR的垃圾回收机制,并不使用引用计数。
方便的 gc.get_objects
可以返回一个由Python解释器跟踪的所有对象实例的列表。举个例子:
import gc class test(object): pass def number_of_test_instances(): return len([obj for obj in gc.get_objects() if isinstance(obj, test)]) for i in range(100): t = test() print "Created and abandoned 100 instances, there are now", \ number_of_test_instances(), \ "instances known to the python interpreter." # note that in normal operation, the GC would # detect the unreachable objects and start # collecting them right away gc.disable() for i in range(100): t = test() t.t = t print "Created and abandoned 100 instances with circular ref, there are now", \ number_of_test_instances(), \ "instances known to the python interpreter." gc.collect() print "After manually doing gc.collect(), there are now", \ number_of_test_instances(), \ "instances known to the python interpreter."
运行这个程序会得到:
Created and abandoned 100 instances, there are now 1 instances known to the python interpreter. Created and abandoned 100 instances with circular ref, there are now 100 instances known to the python interpreter. After manually doing gc.collect(), there are now 1 instances known to the python interpreter.