J'essaie d'écrire une bibliothèque de mémoisation qui utilise Spinve pour stocker le Valeurs de retour de manière persistante. Si j'ai des fonctions mémorisées appelant d'autres fonctions mémorisées, je me demande comment ouvrir correctement le fichier de tablette.
$ 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
3 Réponses :
Vous ouvrez deux fois le fichier mais ne la fermez jamais pour mettre à jour le fichier pour n'importe quelle utilisation. Utilisez f.close () code> à la fin. P>
Vient de regarder ça. Vous ne mettez pas à jour à partir de la première partie, donc il n'y a nulle part pour le "là" pour y aller car il n'existe pas encore. C'est comme ouvrir deux fenêtres de celui-ci
Non, vous n'avez peut-être pas imbriqué Le module d'étagère ne prend pas en charge l'accès simulé en lecture / écriture simultanée aux objets disponibles. (Plusieurs accès simultanés de lecture sont sûrs.) Lorsqu'un programme dispose d'une tablette ouverte pour écrire, aucun autre programme ne devrait l'avoir ouvert à la lecture ou à l'écriture. Unix Le verrouillage du fichier peut être utilisé pour résoudre ce problème, mais cela diffère entre les versions UNIX et nécessite des connaissances sur la mise en œuvre de la base de données utilisée. P>
blockQuote>
https://docs.python.org/3/library/shelve. HTML # restrictions p> SLAVE CODE> A > cas avec le même nom de fichier. p>
plutôt que d'essayer de nier les appels à ouvrir (qui, comme vous l'avez découvert, ne fonctionne pas), vous pouvez rendre votre décorateur à conserver une référence à la poignée renvoyée par sortie: p> Vous pouvez également implémenter le décorateur à l'aide d'un dès qu'il n'y a pas d'autres références à une poignée, ce sera supprimé du dictionnaire. Étant donné que notre poignée ne dépasse que lorsque l'appel le plus externe à une fonction décorée se termine, nous aurons toujours une entrée dans la dicte pendant qu'une poignée est ouverte et qu'aucune entrée juste après sa fermeture. P> p> shelve.open code>, puis si Il existe et est toujours ouvert, réutiliser que pour les appels ultérieurs:
faiblesvalueddictionnaire code>
, qui ressemble un peu plus lisible: p>
Ce n'est pas ce avec shelve.open (nom de fichier, rétablissement = true) comme c: code> fermez l'étagère après ce bloc? Dans ce cas, il ne sera pas ouvert la prochaine fois?
@ Saul.shaanabrook Oui, mais le décorateur vérifie cela. Avec le pas hasattr (getattr (cache, marque_name) .dict, "fermé") code> partie du
si code> instruction.
cache.
@ Saul.Shaanabrook Aussi, je viens de modifier ma réponse afin que le décorateur prend en charge l'utilisation des poignées de conservation pour plusieurs fichiers de cache. Et j'ai mis à jour la section de sortie pour refléter la sortie lorsque le cache n'existe pas déjà.
Je reçois une erreur lorsque j'exécute ce script: Gist.github.com/saulshanabrook/e5000eebeffde91C7453
YEP La version mise à jour fonctionne. Merci beaucoup! c'est parfait
J'ai créé une version mise à jour (je pense) est un peu plus simple gist.github.com/saulshanabrook/e62A5669FE6FB87220D6 < / a>
@ Saul.shaanabrook Il est plus simple, mais cela ne fonctionnera pas si vous apportez des appels imbriqués vers des méthodes décorées à l'aide de code> code>, mais avec des valeurs différentes pour FileName code>. Il ne fermez pas non plus l'étagère si une exception non capturée se produit dans
user_function code> (c'est pourquoi vous utilisez
avec ci-dessus.open (...) code> en premier lieu).
Pouvez-vous commenter la sécurité de votre exemple de votre exemple? C'est à dire. Sera-t-il sauvegarder avoir des fonctions décorées appelées à partir de plusieurs threads? Utiliseront-ils alors le même manche? Et cela sera-t-il sauvegarder?
@Martinito Ce n'est pas un fil-sûr comme écrit. étagère code> ne prend pas en charge l'accès simultané de lecture / écriture à Splasved Les objets (bien que des lectures simultanées sont correctes). Donc, vous auriez besoin de protéger l'accès à l'étagère avec un mutex pour vous assurer qu'un seul thread l'utilise à la fois.
Je pense que vous ne devriez pas avoir deux pointeurs d'écriture ouverts sur le même fichier. Cela conduira presque certainement à un comportement indésirable ... Utilisez plutôt
fichier.seek (0) code> si vous souhaitez revenir à la Début d'un fichier ouvert
Ok, a du sens, mais je ne veux vraiment pas revenir au début des fichiers. Je veux fondamentalement le deuxième
Ouvrir code> pour utiliser le fichier déjà ouvert du premier, s'il a déjà été ouvert, sinon l'ouvrir.
c'est évidemment toujours ouvert depuis que vous êtes toujours dans son bloc de contexte, sauf si vous la fermez explicitement quelque part
@ Saul.shaanabrook Il est difficile de vous dire comment vous devriez faire cela sans une meilleure idée de la manière dont votre bibliothèque est organisée. Les fonctions de mémoisation sont-elles de toutes les parties de la même classe?
@Dano j'ai mis à jour ma question avec un exemple spécifique. Est-ce que ça fait du sens?
@Dano mis à jour à nouveau, avec l'exemple de travail (sauf non)
Compte tenu de votre exemple mis à jour, la question réelle n'est pas " peut
Ouvrir code> être appelée à une mode imbriquée i>?", Mais plutôt, " peut
shelve.open code> être appelé à une mode imbriquée i>? ".
@ Robᵩ Merci pour la suggestion, terminée