Ich versuche, eine Memoization-Bibliothek zu schreiben, die shelve verwendet, um die Rückgabewerte persistent zu speichern. Wenn ich Memo-Funktionen habe, die andere Memo-Funktionen aufrufen, frage ich mich, wie ich die Shelf-Datei richtig öffne.Kann Pythons shelve.open verschachtelt aufgerufen werden?
import shelve
import functools
def cache(filename):
def decorating_function(user_function):
def wrapper(*args, **kwds):
key = str(hash(functools._make_key(args, kwds, typed=False)))
with shelve.open(filename, writeback=True) as cache:
if key in cache:
return cache[key]
else:
result = user_function(*args, **kwds)
cache[key] = result
return result
return functools.update_wrapper(wrapper, user_function)
return decorating_function
@cache(filename='cache')
def expensive_calculation():
print('inside function')
return
@cache(filename='cache')
def other_expensive_calculation():
print('outside function')
return expensive_calculation()
other_expensive_calculation()
Außer dies nicht funktioniert,
$ python3 shelve_test.py
outside function
Traceback (most recent call last):
File "shelve_test.py", line 33, in <module>
other_expensive_calculation()
File "shelve_test.py", line 13, in wrapper
result = user_function(*args, **kwds)
File "shelve_test.py", line 31, in other_expensive_calculation
return expensive_calculation()
File "shelve_test.py", line 9, in wrapper
with shelve.open(filename, writeback=True) as cache:
File "/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/shelve.py", line 239, in open
return DbfilenameShelf(filename, flag, protocol, writeback)
File "/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/shelve.py", line 223, in __init__
Shelf.__init__(self, dbm.open(filename, flag), protocol, writeback)
File "/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/dbm/__init__.py", line 94, in open
return mod.open(file, flag, mode)
_gdbm.error: [Errno 35] Resource temporarily unavailable
Was Sie für eine Lösung dieser Art von Problem zu empfehlen.
Ich denke, Sie sollten nicht zwei offene Schreibzeiger auf die gleiche Datei haben .. das wird fast sicher zu unerwünschtem Verhalten führen ... verwenden Sie stattdessen 'file.seek (0)', wenn Sie zurück zum Anfang von gehen wollen eine offene Datei –
OK, macht Sinn, aber ich möchte nicht wirklich zum Anfang von irgendwelchen Dateien zurückkehren. Ich möchte grundsätzlich zum zweiten 'open' greifen, um die bereits geöffnete Datei des ersten zu verwenden, wenn sie schon geöffnet wurde, wenn nicht, dann öffne sie. –
Offensichtlich immer noch geöffnet, da Sie immer noch in seinem Kontextblock sind, es sei denn, Sie haben es explizit irgendwo geschlossen –