1

PyCLIPS を利用して CLIPS を Python に統合します。Python メソッドは、 を使用して CLIPS に登録されclips.RegisterPythonFunction(method, optional-name)ます。いくつかの関数を登録する必要があり、コードを明確にしたいので、登録を行うデコレーターを探しています。

これが現在行われている方法です:

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))

メソッドのコーディングを保持し、それらを 1 か所に登録します。

NB: CLIPS プロセスが次のような別のプロセスで実行されるマルチプロセッサ セットアップでこれを使用します。

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()
4

3 に答える 3

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__

于 2012-05-16T12:57:18.970 に答える
0

CLIPS に登録するメソッドにデコレータを使用して属性を設定し、initで inspect を使用してメソッドをフェッチして登録することで、現在は機能しています。命名戦略を使用することもできますが、登録をより明確にするためにデコレータを使用することをお勧めします。CLIPS 環境を初期化する前に Python 関数を登録できます。これが私がやったことです。

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")
)

誰かがよりエレガントなアプローチを知っているなら、私に知らせてください。

于 2012-05-17T09:48:30.417 に答える
0

メソッドを登録する前に CLIPS 環境を初期化する必要があるため、mata によって提案されたエレガントなソリューションは機能しないようです。
私は Python の専門家ではありませんが、いくつかの検索では、inspect.getmembers()hasattr( ) の組み合わせがうまくいくようです。クラスのすべてのメンバーをループして、@clips_callable属性を持つメンバーを登録できます。クリップスへ。

于 2012-05-17T04:43:13.813 に答える