Temporary Shelves?
I am designing a class that has undo/redo functionality and has to temporarily store a lot of data. I'm currently implementing a "temporary" file by overloading the del operator to delete the file when the class is garbage collected, but I have to believe there is a better way to do this. I have tried using the tempfile module, but it doesn't work because the shelve module expects a name, not a file object (grr).
Anyway, was wondering if anyone had a better way to do this. Important parts of the code are below.
import os, shelve
from time import time
c开发者_Go百科lass 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
Depending on how your code is run you can still encounter a race condition where two different processes obtain the same timestamp and same filename, rare as that might be. Adding the current process id would help mitigate this, but I would recommend you stick with using the tempfile module.
If you just need the temporary file's name, you can use tempfile.mkstemp and close the returned file descriptor before using the filename:
import os, tempfile
fd, self._undo_fname = tempfile.mkstemp(suffix='.undoredo', dir='/tmp')
os.close(fd)
self._undo_buffer = shelve.open(self._undo_fname)
shelve uses anydbm to detect the type of the database used in the file.
You could create a tempfile with mkstemp()
and put an empty bsddb (or whatever you prefer) in there and then pass that filename to shelve
精彩评论