Sharing objects between processes

ET phu at 2drpg.org
Tue Mar 10 00:48:27 CET 2009


On Mon, 2009-03-09 at 14:57 -0700, Aaron Brady wrote:\ 
> 
> import threading
> import time
> 
> 
> class Globals:
> 	cont= True
> 	content= { }
> 	lock_content= threading.Lock( )
> 
> def read( ):
> 	out= open( 'temp.txt', 'w' )
> 	while Globals.cont:
> 		with Globals.lock_content:
> 			rep= repr( Globals.content )
> 		out.write( rep )
> 		out.write( '\n' )
> 		time.sleep( 1 )
> 
> def write_random( ):
> 	import random
> 	while Globals.cont:
> 		num= random.randint( 1, 100 )
> 		letter= random.choice( 'abcedfghij' )
> 		with Globals.lock_content:
> 			Globals.content[ num ]= letter
> 		time.sleep( 1 )
> 
> def write_user_inp( ):
> 	next_key= 101
> 	while Globals.cont:
> 		us_in= input( '%i--> '% next_key )
> 		if not us_in:
> 			Globals.cont= False
> 			return
> 		us_in= us_in[ :10 ]
> 		print( 'You entered: %s'% us_in )
> 		with Globals.lock_content:
> 			Globals.content[ next_key ]= us_in
> 		next_key+= 1
> 
> read_thr= threading.Thread( target= read )
> read_thr.start( )
> wri_rand_thr= threading.Thread( target= write_random )
> wri_rand_thr.start( )
> wri_user_thr= threading.Thread( target= write_user_inp )
> wri_user_thr.start( )
> 
> read_thr.join( )
> wri_rand_thr.join( )
> wri_user_thr.join( )
> 
> Which is about the complexity of what you asked for.  It wasn't tested
> with multiprocessing.  Ver 3.0.1.
> --
> http://mail.python.org/mailman/listinfo/python-list

Wow, thanks for taking the time to put that together!  Unfortunately,
I've attempted to modify it to use multiprocessing without success.
This works when the threading import is used, falls through with
multiprocessing, and runs with processing, though modifications to the
Globals class do not stick:

from __future__ import with_statement

#from threading import Thread as ControlType, Lock
#from multiprocessing import Process as ControlType, Lock
from processing import Process as ControlType, Lock

import time


class Globals:
        cont= True
        content= { }
        lock_content= Lock( )
        inputs = ['itext', 'text input', 'testing text', 'test']

def read( ):
        #out= open( 'temp.txt', 'w' )
        while Globals.cont:
                with Globals.lock_content:
                        rep= repr( Globals.content )
                print rep
                #out.write( rep )
                #out.write( '\n' )
                time.sleep( 1 )

def write_random( ):
        import random
        while Globals.cont:
                num= random.randint( 1, 100 )
                letter= random.choice( 'abcedfghij' )
                with Globals.lock_content:
                        Globals.content[ num ]= letter
                time.sleep( 1 )

def write_user_inp( ):
        import random
        next_key= 101
        while Globals.cont:
                if len(Globals.inputs):
                    us_in = Globals.inputs.pop()
                else:
                    Globals.cont= False
                    return
                us_in= us_in[ :10 ]
                print( 'You entered: %s'% us_in )
                with Globals.lock_content:
                        Globals.content[ next_key ]= us_in
                next_key+= 1
                time.sleep( 1 )

read_thr= ControlType( target= read )
read_thr.start( )

wri_rand_thr= ControlType( target= write_random )
wri_rand_thr.start( )

wri_user_thr= ControlType( target= write_user_inp )
wri_user_thr.start( )

read_thr.join( )
wri_rand_thr.join( )
wri_user_thr.join( )


However, I think I (freaking finally) managed to get this working after
reading the syncmanager documentation for the umpteenth time; it
involves extending the SyncManager class to allow an arbitrary class as
a member (this might be possible just by calling register(...) on
SyncManager itself, but this is how the doc said to handle it).  It also
provides its own Lock implementations, which I used within the new
managed class to apply with locking:


from __future__ import with_statement

from multiprocessing import Process, Lock, current_process
from multiprocessing.managers import SyncManager

from random import choice, randint
from time import sleep

class TestClass(object):
    name = 'testclassname'
    lock = None
    
    def setval(self, value):
        with self.lock:
            self.name = value
    
    def getval(self):
        with self.lock:
            return self.name
    
    def __init__(self, lock):
        self.lock = lock

class TestManager(SyncManager):
    pass

TestManager.register('TC', TestClass)

manager = TestManager()
manager.start()

class TestProcess(Process):
    obj = None
    new_name = None
    
    def __init__(self, obj):
        self.obj = obj
                
        Process.__init__(self)
    
    def run(self):
        for i in range(5000):
            name = choice('abcedfghij') + str(randint(20, 500))
            print "setting from", obj.getval(), "to", name, "in",
current_process().name
            self.obj.setval(name)
        #    sleep(1)
    
if __name__ == '__main__':
    lock = manager.Lock()
    
    obj = manager.TC(lock)
    
    p1 = TestProcess(obj)
    p2 = TestProcess(obj)

    p1.start()
    p2.start()

    p1.join()
    p2.join()


Putting this up for posterity in case anyone with the same problem
happens upon it.  Thanks again, Aaron, for working through this with me!




More information about the Python-list mailing list