2012-05-16 3 views
1

Python에 CLIPS를 통합하기 위해 PyCLIPS를 사용합니다. Python 메소드는 clips.RegisterPythonFunction(method, optional-name)을 사용하여 CLIPS에 등록됩니다. 여러 함수를 등록해야하고 코드를 명확하게 유지하려면 등록을 수행 할 데코레이터를 찾고 있습니다.PyClips에서 Python 메소드를 등록하는 데코레이터

가 현재 수행하는 방법이다 :

class CLIPS(object): 
... 
    def __init__(self, data): 
     self.data = data 
     clips.RegisterPythonFunction(self.pyprint, "pyprint") 
    def pyprint(self, value): 
     print self.data, "".join(map(str, value)) 

이 내가 그것을하고 싶은 방법입니다

class CLIPS(object): 
... 
    def __init__(self, data): 
     self.data = data 
     #clips.RegisterPythonFunction(self.pyprint, "pyprint") 
    @clips_callable 
    def pyprint(self, value): 
     print self.data, "".join(map(str, value)) 

그것은 방법의 코딩을 유지하고 한 장소에 등록 .

주의 : 이런 식으로 할

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") 
    def Run(self, cycles=None): 
     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)) 
     self.c.Run() 

if __name__ == "__main__": 
    p = multiprocessing.current_process() 
    c = CLIPS("%s %s" % (p.name, p.pid)) 
    c.Run() 
    # Now run CLIPS from another process 
    cp = CLIPSProcess() 
    cp.start() 
+0

파이썬에 대해 모르겠다. CLIPS와 C#을 통합하고 루프에 메소드를 등록하는 환경이있다. 그러나 당신의 방법 "pyprint"의 이름에서 아마도 CLIPS 출력을 파이썬으로 라우팅하기 위해 CLIPS 라우터를 사용해야 할 것입니다. –

+0

pyprint는 간단한 테스트입니다. 나는 파이썬 함수를 사용하여 사실을 주장하고 멋진 것을 호출 할 것이다. – Lemoi

답변

0

데코레이터를 사용하여 CLIPS에 등록 할 메소드의 속성을 설정하고 init의 inspect를 사용하여 메소드를 가져 와서 등록하십시오. 몇 가지 이름 지정 전략을 사용할 수도 있지만, 데코레이터를 사용하여 등록을보다 명확하게하는 것이 더 좋습니다. Python 함수는 CLIPS 환경을 초기화하기 전에 등록 할 수 있습니다. 이것이 내가 한 일이다.

import inspect 

def clips_callable(func): 
    from functools import wraps 
    @wraps(func) 
    def wrapper(*__args,**__kw): 
     return func(*__args,**__kw) 
    setattr(wrapper, "clips_callable", True) 
    return wrapper 

class CLIPS(object): 
    def __init__(self, data): 
     members = inspect.getmembers(self, inspect.ismethod) 
     for name, method in members: 
      try: 
       if method.clips_callable: 
        clips.RegisterPythonFunction(method, name) 
      except: 
       pass 
... 
    @clips_callable 
    def pyprint(self, value): 
     print self.data, "".join(map(str, value)) 

완벽을 기하기 위해 test.clp의 CLIPS 코드가 아래에 포함되어 있습니다.

(defrule MAIN::start-me-up 
    => 
    (python-call pyprint "Hello world") 
) 

누군가보다 세련된 접근 방법을 알고 있다면 알려 주시기 바랍니다.

1

그것은 매우 간단해야한다 : 나는 클립 프로세스가이 같은 별도의 프로세스에서 실행되는 다중 설정이를 사용

# mock clips for testing 
class clips: 
    @staticmethod 
    def RegisterPythonFunction(func, name): 
     print "register: ", func, name 

def clips_callable(fnc): 
    clips.RegisterPythonFunction(fnc, fnc.__name__) 
    return fnc 

@clips_callable 
def test(self): 
    print "test" 

test() 

편집 : 클래스 메소드에서 사용되는 경우 언 바운드 메소드 만 등록합니다. 따라서 첫 번째 인수로 클래스의 인스턴스없이 함수를 호출하면 작동하지 않습니다. 따라서 모듈 수준 함수는 등록 할 수 있지만 클래스 메서드는 등록 할 수 없습니다. 그렇게하려면 __init__에 등록해야합니다.

+0

글쎄, 작동하지 않고 다음과 같은 오류가 있습니다 : [PYTHONXC1] 호출에 대한 기능 호출이 실패했습니다. [PRCCODE4] defrule start-me-up 동작 중에 실행이 중지되었습니다. 나는 이것이 등록 될 때 언 바운드되는 방법과 관련이 있다고 생각한다. 이 함수는 클래스가 인스턴스화되기 전에 등록됩니다. 인스턴스의 데이터에 액세스해야합니다. – Lemoi

+0

클립 자체는 모르지만 데코레이터는 작동합니다. 문제는 아마 데코레이터가 클래스를 생성 할 때 한 번만 실행된다는 것입니다. 등록은 각 인스턴스에 대해 수행되어야합니다. 그런 다음 당신은'__init__' 내에서 그것을해야합니다. – mata

+0

하지만 어떻게? 누군가 어떤 종류의 데코레이터를 사용하여 채워지거나 클래스의 이름을 인식하고 __init__ 동안 루프에 등록하는 클래스 내의 목록을 제안했습니다. 나는 이런 물건을별로 좋아하지 않아. – Lemoi

0

CLIPS 환경을 메소드를 등록하기 전에 초기화해야하기 때문에 mata에서 제안한 멋진 솔루션이 작동하지 않는 것 같습니다.
저는 파이썬 전문가는 아니지만 일부 검색에서 inspect.getmembers()hasattr()의 조합이 여러분을 대신하여 속임수를 쓰는 것처럼 보입니다. 클래스의 모든 구성원을 반복하고 @clips_callable 속성을 CLIPS에 등록 할 수 있습니다.

관련 문제