On 14 May, 2012, at 11:25, Schneider wrote:

> Dames, heren,
>  
> Omdat ik weinig ervaring met decorators en multiprocessing heb, ben ik opzoek 
> naar een beetje hulp.
> Ik maak gebruik van CLIPS via PyClips (http://pyclips.sourceforge.net/) 
> waarbij CLIPS in een apart proces gestart wordt i.v.m. performance e.d. Om 
> Python aan te kunnen roepen vanuit CLIPS, moeten de Python functies in CLIPS 
> worden geregistreerd.
> Meest basale vorm zonder decorators.
>  
> import clips
> import multiprocessing
>  
> class CLIPS(object):
>     def __init__(self, data):
>         self.environment = clips.Environment()
>         self.data = data
>         clips.RegisterPythonFunction(self.pyprint, "pyprint")
>         self.environment.Load("test.clp")
>         self.environment.Reset()
>         self.environment.Run()
>     def pyprint(self, value):
>         print self.data, "".join(map(str, value))
>  
> class CLIPSProcess(multiprocessing.Process):
>     def run(self):
>         p = multiprocessing.current_process()
>         self.c = CLIPS("%s %s" % (p.name, p.pid))
>         pass
>    
> if __name__ == "__main__":
>     cp = CLIPSProcess()
>     cp.start()
>  
> Inhoud van test.clp is:
>  
> (defrule MAIN::start-me-up
>        =>
>        (python-call pyprint "Hello world")
> )                      
>  
> Output is CLIPSProcess-1 2456 Hello world
> Werkt goed. Nu wil ik heel wat “pyprint” achtige functies kunnen registreren 
> via iets als:
>  
>     @clips_callable
>     def pyprint(self, value):
>         …
>  
> zonder dat ik steeds clips.RegisterPythonFunction hoef aan te roepen. Een 
> simpele decorator zoals hieronder werkt niet:
>  
> import clips
> import multiprocessing
>  
> def clips_callable(f):
>     from functools import wraps
>     @wraps(f)
>     def wf(*args, **kwargs):
>         print 'calling {}'.format(f.__name__)
>         return f(*args, **kwargs)
>     clips.RegisterPythonFunction(wf, f.__name__)
>     return wf
>  
> class CLIPS(object):
>     def __init__(self, data):
>         self.environment = clips.Environment()
>         self.data = data
>         #clips.RegisterPythonFunction(self.pyprint, "pyprint")
>         self.environment.Load("test.clp")
>         self.environment.Reset()
>         self.environment.Run()
>     @clips_callable
>     def pyprint(self, value):
>         print self.data, "".join(map(str, value))
>  
> class CLIPSProcess(multiprocessing.Process):
>     def run(self):
>         p = multiprocessing.current_process()
>         self.c = CLIPS("%s %s" % (p.name, p.pid))
>         pass
>    
> if __name__ == "__main__":
>     cp = CLIPSProcess()
>     cp.start()
>  
> Met als output
>  
> calling pyprint
>  
> De decorator doet duidelijk niet wat ik wil. Heeft iemand misschien een 
> oplossing?

De decorator wordt aangeroepen bij het uitvoeren van de class definitie, dus 
voordat CLIPS instantie gemaakt wordt.

Om met de decorator hetzelfde gedrag te krijgen als zonder decorator moet je de 
de decorator in twee-en splitsen: de decorator zelf markeert de functies als 
clips_callable (door ze in een lijstje te plaatsen, of een functie attribuut 
toe te voegen), en in __init__ kan je daarna RegisterPythonFunction aanroepen 
voor alle functies die je eerder gemarkeerd hebt.  

Als alle "pyprint" functies methoden van de CLIPS klasse zijn zou je ook het 
patroon kunnen gebruiken dat in cmd.Cmd in de stdlib gebruikt wordt: geeft alle 
CLIPS functies een naam met een specifieke prefix (bijvoorbeeld "def 
clips_pyprint(self, value): ...") en maak in __init__ een loop over alle 
methoden van de klasse en registreer de methoden waarvan de naam met deze 
prefix begint.

Ronald

Attachment: smime.p7s
Description: S/MIME cryptographic signature

_______________________________________________
Python-nl mailing list
Python-nl@python.org
http://mail.python.org/mailman/listinfo/python-nl

Antwoord per e-mail aan