首先,我用flush方法编写了一个录制类:
class Recorder
def __init__(self, buffer_size, path):
self._big_buffer = np.array(*buffer_size)
self._path = path
def push(self, data):
# insert in self._big_buffer
# if self._big_buffer is full:
# self._flush()
def flush(self):
# write buffer to disk (self._path)
然后,我想在退出时刷新:手动停止,崩溃或其他原因。
所以我用过:
def __init__(self):
(...)
atexit.register(self.flush)
它运作得很好。
但是现在,我想录制,停止录制,再次录制,多次,使用不同的缓冲区大小和不同的路径。所以我必须丢弃,然后实现几个Recorder
。它有点有用,但是Recorder
的旧self._big_buffer̀
内存(含有一些胖atexit
)没有被释放,因为它被del
保留了。即使我明确地呼叫atexit.unregister(self._flush)
。
我不能POST
,因为它只是Python 3。
我不想重复使用现有实例,而是放弃旧实例并创建新实例。
你会如何处理这种情况?
答案 0 :(得分:4)
您可以尝试使用对atexit
处理程序的弱引用,因此该对象
如果在其他地方删除,则不会被保留:
import atexit
import weakref
class CallableMethodWeakRef:
def __init__(self, object, method_name):
self.object_ref = weakref.ref(object)
self.method_name = method_name
def __call__(self):
object = self.object_ref()
if object:
getattr(object, self.method_name)()
class Recorder:
def __init__(self, *args):
atexit.register(CallableMethodWeakRef(self, 'flush'))
def flush(self):
print 'flushing'
该方法作为字符串传递,以避免很多问题
绑定方法弱引用,如果你发现它令人不安你可以随时使用
像这样的BoundMethodWeakref
实现:http://code.activestate.com/recipes/578298-bound-method-weakref/
答案 1 :(得分:2)
我会说你试图使用错误的工具。 with
语句和上下文管理器是一个非常好的工具。文件IO是大多数python用户将被引入with语句的主要示例。
f = open("somefile.txt", "w")
try:
f.write("...")
# more file operations
finally:
# regardless of what happens, make sure the files is closed
f.close()
变为:
with open("somefile.txt", "w") as f:
f.write("...")
# more file operations
# close automatically called at the end of the block
您可以为您的班级编写__enter__
和__exit__
方法来创建自己的上下文管理器。
class Recorder
def __init__(self, buffer_size, path):
self._big_buffer = np.array(*buffer_size)
self._path = path
def push(self, data):
# insert in self._big_buffer
# if self._big_buffer is full:
# self._flush()
def flush(self):
# write buffer to disk (self._path)
def __enter__(self):
return self
def __exit__(self, exctype, exception, traceback):
# If an exception was thrown in the with block you will get the details here.
# If you want the say that the exception has been handled and for it not to be
# raised outside the with block then return True
self.flush()
# self.close() ?
然后您将使用Recorder
对象,如:
with Recorder(...) as recorder:
# operations with recorder
...
# regardless of what happens the recorder will be flushed at this point
答案 2 :(得分:0)
答案 肯定是允许class Program
{
static void Main(string[] args)
{
Random rand = new Random();
int number = rand.Next(1, 1000);
byte[] intBytes = BitConverter.GetBytes(number);
string answer = "";
for (int i = 0; i < intBytes.Length; i++)
{
answer += intBytes[i] + @"\";
}
Console.WriteLine(answer);
Console.WriteLine(number);
Console.ReadKey();
}
}
随意更改路径和缓冲区特征。你说&#34;我不想重复使用现有的实例,而是放弃旧的实例并创建新的实例。&#34; 但是你没有给出任何理由,
除了你假设&#34;较旧的记录器的记忆(包含一些胖Recorder
)没有被释放,因为它被self._big_buffer̀
&#34;保留了。 ,我认为这是不正确的。
虽然atexit
确实保留了对记录器对象的引用,但这只意味着只要记录器引用它就会保留缓冲存储器。添加atexit
方法非常容易,例如
close()
和宾果游戏!不存在对缓冲存储器的引用,它是可收集的。
您的 def close(self):
self.flush()
self._big_buffer = None
方法应该只使用__init__()
注册,然后atexit
方法(执行open()
当前所做的其余工作)可以多次使用,每个一个接着是__init__()
电话。
总之,我认为你的问题需要一个对象。
答案 3 :(得分:0)
您可以从(未公开)atexit._exithandlers
列表中手动删除手柄。
import atexit
def unregister(func, *targs, **kargs):
"""unregister a function previously registered with atexit.
use exactly the same aguments used for before register.
"""
for i in range(0,len(atexit._exithandlers)):
if (func, targs, kargs) == atexit._exithandlers[i] :
del atexit._exithandlers[i]
return True
return False
希望有帮助。