问题
I'm attempting to build a python script that has a pool of worker processes (using mutiprocessing.Pool) across a large set of data.
I want each process to have a unique object that gets used across multiple executes of that process.
Psudo code:
def work(data):
#connection should be unique per process
connection.put(data)
print 'work done with connection:', connection
if __name__ == '__main__':
pPool = Pool() # pool of 4 processes
datas = [1..1000]
for process in pPool:
#this is the part i'm asking about // how do I really do this?
process.connection = Connection(conargs)
for data in datas:
pPool.apply_async(work, (data))
回答1:
I think something like that should work (not tested)
def init(*args):
global connection
connection = Connection(*args)
pPool = Pool(initializer=init, initargs=conargs)
回答2:
It may be easiest to create the mp.Process
es directly (without mp.Pool
):
import multiprocessing as mp
import time
class Connection(object):
def __init__(self,name):
self.name=name
def __str__(self):
return self.name
def work(inqueue,conn):
name=mp.current_process().name
while 1:
data=inqueue.get()
time.sleep(.5)
print('{n}: work done with connection {c} on data {d}'.format(
n=name,c=conn,d=data))
inqueue.task_done()
if __name__ == '__main__':
N=4
procs=[]
inqueue=mp.JoinableQueue()
for i in range(N):
conn=Connection(name='Conn-'+str(i))
proc=mp.Process(target=work,name='Proc-'+str(i),args=(inqueue,conn))
proc.daemon=True
proc.start()
datas = range(1,11)
for data in datas:
inqueue.put(data)
inqueue.join()
yields
Proc-0: work done with connection Conn-0 on data 1
Proc-1: work done with connection Conn-1 on data 2
Proc-3: work done with connection Conn-3 on data 3
Proc-2: work done with connection Conn-2 on data 4
Proc-0: work done with connection Conn-0 on data 5
Proc-1: work done with connection Conn-1 on data 6
Proc-3: work done with connection Conn-3 on data 7
Proc-2: work done with connection Conn-2 on data 8
Proc-0: work done with connection Conn-0 on data 9
Proc-1: work done with connection Conn-1 on data 10
Notice the Proc
numbers correspond to the same Conn
number each time.
回答3:
Process local storage is pretty easy to implement as a mapping container, for anyone else getting here from Google looking for something similar (note this is Py3, but easily convertible to 2's syntax (just inherit from object
):
class ProcessLocal:
"""
Provides a basic per-process mapping container that wipes itself if the current PID changed since the last get/set.
Aka `threading.local()`, but for processes instead of threads.
"""
__pid__ = -1
def __init__(self, mapping_factory=dict):
self.__mapping_factory = mapping_factory
def __handle_pid(self):
new_pid = os.getpid()
if self.__pid__ != new_pid:
self.__pid__, self.__store = new_pid, self.__mapping_factory()
def __delitem__(self, key):
self.__handle_pid()
return self.__store.__delitem__(key)
def __getitem__(self, key):
self.__handle_pid()
return self.__store.__getitem__(key)
def __setitem__(self, key, val):
self.__handle_pid()
return self.__store.__setitem__(key)
See more @ https://github.com/akatrevorjay/pytutils/blob/develop/pytutils/mappings.py
回答4:
You want to have an object residing in shared memory, right?
Python has some support for that in its standard library, but it's kinda poor. As far as I recall, only Integers and some other primitive types can be stored.
Try POSH (Python Object Sharing): http://poshmodule.sourceforge.net/
来源:https://stackoverflow.com/questions/5355827/python-2-6-process-local-storage-while-using-multiprocessing-pool