2017-09-14 4 views
0

次のコードをEclipse経由でWindowsで実行するのに問題があります。コードはDoug Hellmanからです:pythonマルチプロセッシングpickling/manager/miscエラー(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)) 

私はProcessの引数としてpoolに渡すと、いくつかの酸洗問題が原因であると仮定し、次のエラーを取得します。

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 

同様の質問のanswerは、私は、トップレベルの関数呼び出しでpoolを初期化するが、私はこの例にそれを適用する方法を知っていないことを示唆しているようです。 にActivePoolを初期化しますか?それはヘルマンの例の精神を破るようです。

answerはunpickleableオブジェクトを削除し、unpickle化する際にそれらを再構築するために、私は__getstate____setstate__を使用することをお勧めしますが、私はプロキシでこれを行うには良い方法は、マネージャーのようなオブジェクト、そして私が実際に何を知っていないかわかりませんunpickleableオブジェクトはです。

この例を最小限の変更で動作させる方法はありますか?私は本当にボンネットの下で何が起こっているのか理解したい。ありがとう!

編集 - 問題は解決:

酸洗問題は後知恵ではかなり明白でした。 ActivePoolの__init__には、unpicklableと思われるManager()オブジェクトが含まれていました。我々はself.mgrを削除し、1行にリストProxyObjectを初期化する場合のコードは、ヘルマンの例に従って正常に動作します:読み取り

def __init__(self): 
     super(ActivePool, self).__init__() 
     self.active = multiprocessing.Manager().list() 
     self.lock = multiprocessing.Lock() 

答えて

0

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

私はLinuxを実行していることだし、期待どおりに、Windowsは異なる振る舞い作品understanding-multiprocessing-shared-memory-management-locks-and-queues-in-pyt

args=(s, pool)のどのパラメータがエラーを発生させるかを判断するには、globalとして使用します。
変更:

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?

あなた__main__プロセスが終了するが、そのため、すべてのプロセスが実行の予想外の位置で死に始めました。

for j in jobs: 
     j.join() 

    print('EXIT __main__') 

は、Pythonでテスト:すべてのプロセスが完了するまで__main__待ち時間をできるように最後に簡単な.join()を追加し、私はすべてのロック呼び出しをコメントアウト3.4.2

+0

と同じエラーを取得。 Hellmanの例では 'join()'がありましたが、コードスニペットに追加するのを忘れてしまいました。他のアイデア? – Zhulu

+0

私は問題を解決する前に、グローバルセマフォとグローバルプールハンドルを作ってから、 'args(s、)'、 'args(pool)'、 'args(s、pool)'でコードを実行しました。 3人とも残念ながらうまくいきませんでした。2番目と3番目のメソッドは同じエラーになり、最初のメソッドは 'AttributeError:NoneType 'オブジェクトに属性' makeActive 'がありませんでした。私はグローバルを作り、 'pool = None'と ' def initialize_pool(): グローバルプール\ プール= ActivePool() 'のように初期化しました。 – Zhulu

関連する問題