临时架子?

1 投票
2 回答
1023 浏览
提问于 2025-04-16 15:05

我正在设计一个类,这个类需要有撤销和重做的功能,并且要临时存储大量数据。目前,我通过重载del操作符来实现一个“临时”文件,这样当这个类被垃圾回收时,就会删除这个文件。不过我觉得这样做可能还有更好的方法。我尝试过使用tempfile模块,但它不行,因为shelve模块需要的是一个名字,而不是文件对象(真让人烦)。

总之,我想知道有没有人有更好的解决办法。下面是代码的重要部分。

import os, shelve
from time import time
class DataHandlerUser(DataHandler):
   def __init__(self, data):
      # storing items
      self.__unredofilename = os.path.dirname(__file__) + '/.undoredo' + str(time()) + '.pyworkbooks'
      try:
         os.remove(self.__unredofilename)
      except OSError: pass

      self._undoredoBuffer = shelve.open(self.__unredofilename)
      # ... rest of init


   def __del__(self):
      # simple check to make sure not tampered with
      if '.undoredo' not in self.__unredofilename or '.pyworkbooks' not in self.__unredofilename:
         raise Exception('Critical Error: Internal filename for undo/redo operations tampered with')
      try:
         os.remove(self.__unredofilename)
      except OSError: pass

2 个回答

2

shelve使用anydbm来判断文件中使用的数据库类型。

你可以用mkstemp()创建一个临时文件,然后在里面放一个空的bsddb(或者你喜欢的其他类型),接着把这个文件名传给shelve。

4

根据你的代码运行方式,你可能会遇到一种情况,叫做“竞争条件”。这意味着两个不同的程序可能会同时获得相同的时间戳和文件名,虽然这种情况很少见。为了减少这种情况的发生,可以加上当前的进程ID,但我建议你还是使用tempfile模块。

如果你只需要临时文件的名字,可以使用tempfile.mkstemp,然后在使用文件名之前关闭返回的文件描述符:

import os, tempfile
fd, self._undo_fname = tempfile.mkstemp(suffix='.undoredo', dir='/tmp')
os.close(fd)
self._undo_buffer = shelve.open(self._undo_fname)

撰写回答