2017-09-14 4 views
0

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() 

Répondre

0

Comment: The 'join()' was in the Hellman example, but I forgot to add it into the code snippet. Any other ideas?

Je suis sous Linux et il fonctionne comme prévu, Windows se comportent différent lire understanding-multiprocessing-shared-memory-management-locks-and-queues-in-pyt

Pour déterminer quel paramètre de args=(s, pool) déclenche l'erreur, en supprimer un et l'utiliser comme global.
Change:

def worker(s): 
    ... 

     args=(s,), 

Note: There is no need to enclose a multiprocessing.Manager().list() with a Lock() .
This is not the culprit of your error.


Question: Is there any way I can make this example work with minimal changes?

Votre processus __main__ se termine donc tout a commencé processus meurent à la position unpredicted d'exécution. Ajouter simple, un .join() à la fin de laisser la __main__ attendre jusqu'à ce que tous les processus effectués:

for j in jobs: 
     j.join() 

    print('EXIT __main__') 

testé avec Python: 3.4.2

+0

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

+0

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