Pregunta

He creado un simple RPC servidor para realizar ciertas tareas comunes a nuestros equipos, pero que son llamados de diferentes redes. Las miradas servidor de esta manera (no incluyo el manejo de errores por razones de brevedad):

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

Esto es muy simple: el servidor recibe una solicitud JSON RPC desde el cliente, busca el método, y llama al método de pasar los parámetros. El método en sí mismo es el que devolver la respuesta JSON RPC. Para los menos familiar, un JSON RPC ve aproximadamente así:

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

El servidor RPC ya que tengo que sirve a mis propósitos actuales muy bien (como se puede imaginar, mi tarea es muy simple). Pero voy a tener que seguir añadiendo métodos como la complejidad de los aumentos de trabajo.

No quiero abrir el archivo principal y añadir otro def method3(...) y, dos semanas después, añadir def method4(...) y así sucesivamente; el código crecería demasiado rápido y el mantenimiento sería más difícil.

Por lo tanto, mi pregunta es: ¿Cómo puedo crear una arquitectura que me permite registrar métodos en el servidor . Una ventaja sería tener una carpeta separada sosteniendo un archivo por cada método, por lo que fácilmente se pueden compartir y mantenidos. Esta "arquitectura" sería también me permitirá aplazar el mantenimiento de algunos métodos a otra persona, independientemente de su comprensión de trenzado.

No me importa si tengo que reiniciar el servidor cada vez que se ha registrado un nuevo método, sino una obvia ventaja sería si No tener demasiados:.)

Gracias.

¿Fue útil?

Solución

Un poco de un orden bastante grande;) pero aquí hay algunos pasos iniciales para usted (muy fuertemente burlado arriba, detalles trenzados omite, en los ejemplos):

# 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

Si se asume que lo pruebe como si ejecutamos la siguiente:

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

Wold tiene un somemod.py módulo en el mismo directorio que el ejemplo con el siguiente contenido (que reflejan el ejemplo del método .add() arriba):

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

Esto le permite tener un módulo por el método servido. La llamada method(.. anterior pasará siempre la instancia MyProtocol exigible a la que sirve. (Si realmente quiere métodos de instancia, aquí hay instrucciones sobre cómo agregar métodos que utilizan Python: http: // irrepupavel .com / documentos / Python / instancemethod / )

Se necesitará una gran cantidad de control de errores añadido. Por ejemplo, usted necesita una gran cantidad de comprobación de errores en la llamada split() en la línea 2 de dataReceived().

Con esto usted puede tener archivos separados con una sola función en ellos por todos los medios que necesita para el apoyo. De ninguna manera un ejemplo completo, pero puede ser que consiga que va, ya que lo que Your'e buscando es bastante complejo.

En un registro más formal, lo recomiendo un dict en MyProtocol con los nombres de los métodos que usted apoya, a lo largo de las líneas de:

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

Y un método de registro ..

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

.. modificar dataReceived() ..

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

Resumen rápido de un demasiado largo mensaje: la función __import__ ( http: //docs.python .org / biblioteca / functions.html ) con toda seguridad, será una parte clave de su solución.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top