multitraitement.Piscine - PicklingError: ne Peut pas pickle <type de fil conducteur.lock'>: attribut de recherche de fil.serrure a échoué
multiprocessing.Pool
me rend fou...
Je veux mettre à jour de nombreux paquets, et pour chacun d'entre eux, je dois vérifier si il y a plus de version ou pas. Ceci est fait par le check_one
fonction.
Le code principal est dans le Updater.update
méthode: j'ai créer le Pool objet et l'appel de la map()
méthode.
Voici le code:
def check_one(args):
res, total, package, version = args
i = res.qsize()
logger.info('\r[{0:.1%} - {1}, {2} /{3}]',
i / float(total), package, i, total, addn=False)
try:
json = PyPIJson(package).retrieve()
new_version = Version(json['info']['version'])
except Exception as e:
logger.error('Error: Failed to fetch data for {0} ({1})', package, e)
return
if new_version > version:
res.put_nowait((package, version, new_version, json))
class Updater(FileManager):
# __init__ and other methods...
def update(self):
logger.info('Searching for updates')
packages = Queue.Queue()
data = ((packages, self.set_len, dist.project_name, Version(dist.version)) \
for dist in self.working_set)
pool = multiprocessing.Pool()
pool.map(check_one, data)
pool.close()
pool.join()
while True:
try:
package, version, new_version, json = packages.get_nowait()
except Queue.Empty:
break
txt = 'A new release is avaiable for {0}: {1!s} (old {2}), update'.format(package,
new_version,
version)
u = logger.ask(txt, bool=('upgrade version', 'keep working version'), dont_ask=self.yes)
if u:
self.upgrade(package, json, new_version)
else:
logger.info('{0} has not been upgraded', package)
self._clean()
logger.success('Updating finished successfully')
Quand je le lance, j'obtiens cette erreur bizarre:
Searching for updates
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/local/lib/python2.7/dist-packages/multiprocessing/pool.py", line 225, in _handle_tasks
put(task)
PicklingError: Can't pickle <type 'thread.lock'>: attribute lookup thread.lock failed
Vous devez vous connecter pour publier un commentaire.
multitraitement passe des tâches (qui comprennent
check_one
etdata
) pour les processus de travail par le biais d'unmp.SimpleQueue
. Contrairement àQueue.Queue
s, tout mettre dans lemp.SimpleQueue
doit être cliquable.Queue.Queue
s ne sont pas cliquable:les rendements de cette exception:
Votre
data
comprendpackages
, qui est une File d'attente.La file d'attente. Que pourrait être la source du problème.Voici une solution possible: Le
Queue
est utilisé à deux fins:qsize
)Au lieu de l'appeler
qsize
, à part une valeur entre plusieurs processus, nous pourrions utiliser unmp.Value
.Au lieu de stocker les résultats dans une file d'attente, on peut (et devrait) être juste retour des valeurs à partir des appels à
check_one
. Lepool.map
recueille les résultats dans une file d'attente de sa propre fabrication, et renvoie les résultats que la valeur de retour depool.map
.Par exemple:
check_one
une méthode (avec ce hack: stackoverflow.com/questions/1816958/...), mais encore une fois, cela n'a pas fonctionné...multiprocessing.Manager().Queue()
au lieu demultiprocessing.Queue
.Après beaucoup de creuser sur un problème similaire...
Il s'avère également que TOUT objet qui contient un filetage.Condition() de l'objet ne sera JAMAIS ne JAMAIS travailler avec le multitraitement.Piscine.
Voici un exemple
Je suis de l'exécution de cette avec Python 2.7.5 et frappé de la même erreur:
Mais ensuite, il a couru sur python 3.4.1 et ce problème a été résolu.
Bien que je n'ai pas trouvé utile solutions de contournement encore pour ceux d'entre nous sont encore sur la 2.7.x.
threading.Lock
ne peut toujours pas être marinés (même si, comme vous l'avez mentionné,threading.Condition
peut être).threading.Lock
objets ne peuvent toujours pas être traitées en Python 3.6.2.J'ai connu ce problème avec la version de python 3.6 sur docker. Changé la version 3.7.3 et il a été résolu.