次のコードを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()
と同じエラーを取得。 Hellmanの例では 'join()'がありましたが、コードスニペットに追加するのを忘れてしまいました。他のアイデア? – Zhulu
私は問題を解決する前に、グローバルセマフォとグローバルプールハンドルを作ってから、 'args(s、)'、 'args(pool)'、 'args(s、pool)'でコードを実行しました。 3人とも残念ながらうまくいきませんでした。2番目と3番目のメソッドは同じエラーになり、最初のメソッドは 'AttributeError:NoneType 'オブジェクトに属性' makeActive 'がありませんでした。私はグローバルを作り、 'pool = None'と ' def initialize_pool(): グローバルプール\ プール= ActivePool() 'のように初期化しました。 – Zhulu