Je rencontre des problèmes pour implémenter un nouvel objet proxy defaultdict
. Le documentation est un peu peur, donc je ne suis pas sûr de savoir comment s'y prendre correctement.Sous-classe multiprocessing.managers.BaseProxy
Je souhaite ajouter un defaultdict
à la liste des types disponibles dans l'instance Manager
. Vous ne pouvez pas utiliser la méthode Manager.register
sur le stock multiprocessing.Manager
donc je l'ai fait mon propre souche directeur de la multiprocessing.mangers.BaseManager
class Manager(BaseManager):
pass
J'ai ensuite créé ma sous-classe de multiprocessing.managers.BaseProxy
à la maison de la defaultdict
(j'ai essayé d'abord d'avoir anthères stub qui serait sous-classe à la fois defaultdict
et BaseProxy
mais cela ne semble pas fonctionner Voici ce que j'ai actuellement:..
class ProxyDefaultDict(BaseProxy):
def __init__(self, default_factory=None, *args, **kwargs):
self.__data = defaultdict(default_factory)
super().__init__(*args, **kwargs)
def _callmethod(self, methodname, args=(), kwds={}):
return getattr(self.__data, methodname)(*args, **kwds)
def _getvalue(self):
return self.__data.copy()
def __repr__(self):
return self.__data.__repr__()
def __str__(self):
return self.__data.__str__()
Manager.register('defaultdict', ProxyDefaultDict)
L'objectif final est d'avoir un dictionnaire partagé qui partage en toute sécurité à travers les processus serrures à clé et fils Il re un exemple de la façon dont je l'image, il serait initialisés:
if __name__ == '__main__':
m = Manager()
d = m.defaultdict(m.Lock)
with d['named_lock']:
print('holding the lock')
Cependant, je l'ai touché quelques problèmes:
Une sous-classe de BaseManager semble être seulement initalizable par un gestionnaire de contexte à savoir
with Manager() as m
. Ce que je voudrais utiliserm = Manager()
dans ce cas - que lemultiprocessing.Manager
permet. Pas la fin du monde mais plus curieux pourquoi c'est le cas et si c'est un signe que je fais quelque chose de mal.Le sous-classement
multiprocessing.managers.BaseManager
indique également que vous perdez les valeurs enregistrées par défaut demultiprocessing.Manager
. Dans ce cas, je dois ré-enregistrer un ProxyLock pour mon manager (dont je ne suis pas sûr de la manière attendue de le faire). Est-il sûr de simplement sous-classermultiprocessing.Manager
directement.Enfin, mon
ProxyDefaultDict
ne semble pas me permettre de remplacer proprement son__init__
. Et je suis fatigué de ne pas appeler leBaseProxy.__init__
lors du sous-classement. Le problème est que BaseProxy accepte également les arguments positionnels. Je suppose que le moyen de contourner ceci est de faire de l'argumentdefault_factory
un argument clé uniquement, mais cela change l'interface attendue endefaultdict
et me fait supposer que je fais quelque chose de mal ici encore. Les autres types commeManager.Lock
semblent être en mesure d'accepter des arguments positionnels.
Merci pour toute aide.
Ah ouais, on dirait que vous pouvez appeler '' register' sur SyncManager' mais pas 'manager', merci. Je reçois une erreur différente lorsque j'essaie d'utiliser une serrure par défaut. Lorsque vous essayez d'utiliser un verrou géré, par exemple 'm.defaultdict (m.Lock)' Je reçois une erreur 'TypeError: Pickling un objet AuthenticationString est interdit pour des raisons de sécurité'. Avec un verrou non géré, j'obtiens un message Unserializable: ('#RETURN',) '. En cours d'exécution sur Python 3.4. J'aurais pensé que si une serrure pouvait être peroxydée, elle pourrait être décapée. –
freebie
Oui, je pense que 3.6 a juste une erreur mise à jour/méthode de détection. Je reçois la même erreur si j'essaie d'utiliser des verrous de threading. Il existe d'autres idées https://stackoverflow.com/questions/17960296/trouble-using-a-lock-with-multiprocessing-pool-pickling-error pour contourner cela. – CasualDemon