質問

シンプルを作成しました RPC チームに共通の特定のタスクを実行するサーバーがありますが、これは異なるネットワークから呼び出されます。サーバーはこのように見えます(Brevityのためにエラー処理を含めません):

from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor
import json

class MyProtocol(Protocol):
    def dataReceived(self, data):
        req = json.loads(data) # create a dictionary from JSON string
        method = getattr(self, req['method']) # get the method
        method(req['params']) # call the method

    def add(self, params):
        result = {} # initialize a dictionary to convert later to JSON
        result['result'] = sum(params) 
        result['error'] = None 
        result['id'] = 1
        self.transport.write(json.dumps(result)) # return a JSON string
        self.transport.loseConnection() # close connection

factory = Factory()
factory.protocol = MyProtocol
reactor.listenTCP(8080, factory)
reactor.run()

これは非常に簡単です。サーバーは、クライアントからJSON RPC要求を受信し、メソッドを探し、パラメーターを通過するメソッドを呼び出します。この方法自体は、JSON RPC応答を返すものです。あまり馴染みのない場合、a JSON RPC このように見えます:

request:
{"method":"my_method", "params":[1,2,3], "id":"my_id"}
response:
{"result":"my_result", "error":null, "id":"my_id"}

私が持っているRPCサーバーは、私の現在の目的を非常にうまく機能させます(想像できるように、私のタスクは非常に簡単です)。しかし、タスクの複雑さが増すにつれて、メソッドを追加し続ける必要があります。

メインファイルを開いてさらに別のファイルを追加したくない def method3(...) そして、2週間後、追加 def method4(...) など。コードが速すぎて、メンテナンスはますます難しくなります。

だから、私の質問は次のとおりです。 どうすればできるようにするアーキテクチャを作成できますか 登録 サーバーへのメソッド. 。ボーナスは、メソッドごとに1つのファイルを保持している別のフォルダーを使用して、簡単に共有および維持できるようにすることです。この「アーキテクチャ」は、ねじれの理解に関係なく、他の誰かにいくつかの方法の維持を延期することもできます。

新しい方法が登録されるたびにサーバーを再起動する必要があるかどうかは気にしませんが、明らかなプラスは私が しないでください 持っている:)。

ありがとう。

役に立ちましたか?

解決

ちょっとした秩序;)しかし、ここにあなたのためのいくつかの最初の手順があります(非常にひどくock笑され、ねじれた詳細を例に掲げています):

# your twisted imports...
import json

class MyProtocol(object): # Would be Protocol instead of object in real code

    def dataReceived(self, data):
        req = json.loads(data) # create a dictionary from JSON string
        modname, funcname = req['method'].split('.')
        m = __import__(modname)
        method = getattr(m, funcname) # get the method
        method(self, req['params']) # call the method

私たちがこれを実行したかのようにあなたがそれを試してみると仮定すると:

mp = MyProtocol()
mp.dataReceived('{"method":"somemod.add", "params":[1,2,3]}')

モジュールがあります somemod.py 次の内容を持つ例と同じディレクトリで(あなたの例をミラーリングする方法 .add() その上):

import json

def add(proto, params):
    result = {} # initialize a dictionary to convert later to JSON
    result['result'] = sum(params)
    result['error'] = None
    result['id'] = 1
    proto.transport.write(json.dumps(result)) # return a JSON string
    proto.transport.loseConnection() # close connection

これにより、メソッドごとに1つのモジュールを提供できます。 method(.. 上記のコールは常にあなたを渡します MyProtocol サービングコール可能なインスタンス。 (本当にインスタンスメソッドが必要な場合は、Pythonを使用してメソッドを追加する方法に関する指示を次に示します。 http://irrepupavel.com/documents/python/instancemethod/ )

多くのエラー処理が追加される必要があります。たとえば、で多くのエラーチェックが必要です split() の2行目に電話してください dataReceived().

これを使用すると、サポートする必要があるすべての方法に対して1つの関数を含む個別のファイルを使用できます。決して完全な例ではありませんが、あなたが探しているものが非常に複雑であるため、あなたを動かすかもしれません。

より正式な登録には、aをお勧めします dictMyProtocol 次の行に沿って、あなたがサポートする方法の名前を使用してください。

# in MyProtocol's __init__() method:
self.methods = {}

と登録方法。

def register(self, name, callable):
    self.methods[name] = callable

..変更 dataReceived()..

def dataReceived(self, data):
    # ...
    modname, funcname = self.methods.get(req['method'], False)
    # ..continue along the lines of the dataReceived() method above

長すぎる投稿のクイックサマリー:the __import__ 働き ( http://docs.python.org/library/functions.html )あなたのソリューションの重要な部分になるでしょう。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top