J'ai quelques problèmes pour exécuter le code suivant sur Eclipse via Windows. Le code est de Doug Hellman:python multitraitement décapage/gestionnaire/erreur misc (de PMOTW)
import random
import multiprocessing
import time
class ActivePool:
def __init__(self):
super(ActivePool, self).__init__()
self.mgr = multiprocessing.Manager()
self.active = self.mgr.list()
self.lock = multiprocessing.Lock()
def makeActive(self, name):
with self.lock:
self.active.append(name)
def makeInactive(self, name):
with self.lock:
self.active.remove(name)
def __str__(self):
with self.lock:
return str(self.active)
def worker(s, pool):
name = multiprocessing.current_process().name
with s:
pool.makeActive(name)
print('Activating {} now running {}'.format(
name, pool))
time.sleep(random.random())
pool.makeInactive(name)
if __name__ == '__main__':
pool = ActivePool()
s = multiprocessing.Semaphore(3)
jobs = [
multiprocessing.Process(
target=worker,
name=str(i),
args=(s, pool),
)
for i in range(10)
]
for j in jobs:
j.start()
for j in jobs:
j.join()
print('Now running: %s' % str(pool))
Je reçois l'erreur suivante, que je suppose est due à une question de décapage avec passage dans pool
comme argument pour Process
.
Traceback (most recent call last):
File "E:\Eclipse_Workspace\CodeExamples\FromCodes\CodeTest.py", line 50, in <module>
j.start()
File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\process.py", line 105, in start
self._popen = self._Popen(self)
File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\context.py", line 223, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\context.py", line 322, in _Popen
return Popen(process_obj)
File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\popen_spawn_win32.py", line 65, in __init__
reduction.dump(process_obj, to_child)
File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\connection.py", line 939, in reduce_pipe_connection
dh = reduction.DupHandle(conn.fileno(), access)
File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\connection.py", line 170, in fileno
self._check_closed()
File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\connection.py", line 136, in _check_closed
raise OSError("handle is closed")
OSError: handle is closed
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\spawn.py", line 99, in spawn_main
new_handle = reduction.steal_handle(parent_pid, pipe_handle)
File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\reduction.py", line 87, in steal_handle
_winapi.DUPLICATE_SAME_ACCESS | _winapi.DUPLICATE_CLOSE_SOURCE)
PermissionError: [WinError 5] Access is denied
Une answer de question similaire semble suggérer que j'initialiser pool
avec un appel de fonction au niveau supérieur, mais je ne sais pas comment l'appliquer à cet exemple. Dois-je initialiser ActivePool
dans worker
? Cela semble vaincre l'esprit de l'exemple de Hellman.
Une autre answer suggère que j'utilise __getstate__
, __setstate__
, pour supprimer les objets unpickleable et les reconstruire quand unpickling, mais je ne sais pas une bonne façon de le faire avec Proxy Objects comme directeur, et je ne sais pas vraiment ce que la objet non pickleable est.
Est-il possible de faire fonctionner cet exemple avec un minimum de changements? Je veux vraiment comprendre ce qui se passe sous le capot. Merci!
Edition - Problème résolu:
La question de décapage était assez évident avec le recul. Le __init__
d'ActivePool contenait un objet Manager() qui semble impossible à masquer. Le code fonctionne normalement comme par exemple de Hellman si on enlève self.mgr
, et initialiser la liste ProxyObject en une ligne:
def __init__(self):
super(ActivePool, self).__init__()
self.active = multiprocessing.Manager().list()
self.lock = multiprocessing.Lock()
Je commentais tous les appels de verrouillage et d'obtenir la même erreur . Le 'join()' était dans l'exemple Hellman, mais j'ai oublié de l'ajouter dans l'extrait de code. D'autres idées? – Zhulu
Avant de résoudre le problème, j'ai créé un sémaphore global et un handle de pool global, puis j'ai exécuté le code avec 'args (s,)', 'args (pool,)', 'args (s, pool)'. Tous les trois n'ont malheureusement pas fonctionné.Les deuxième et troisième méthodes ont abouti à la même erreur et la première méthode a abouti à 'AttributeError: l'objet 'NoneType' n'a pas d'attribut 'makeActive''. J'ai fait les globals et les ai initialisés comme 'pool = None' et ' def initialize_pool(): pool global \ pool = ActivePool() '. – Zhulu