我想使用Python实现某种形式的客户端-服务器连接,并且对于多处理是相当新的。基本上,我有一个类'Manager',它继承自multiprocessing.Process并管理从客户端到不同数据源的连接。此过程具有一些函数,例如“ get_value(key)”,应返回键数据源的值。现在,因为我希望它异步运行,所以我不能简单地从客户端进程中调用此函数。
到目前为止,我的想法是我使用管道连接客户端和管理器进程,然后将消息从客户端发送到管理器以执行此功能。我将通过管道发送一个列表来实现这一点,其中第一个元素是函数的名称,其余元素是实际函数的参数,例如['get_value','datasource1']。然后,该过程将收到此消息,并通过管道将返回值发送给客户端。看起来像这样:
from multiprocessing import Process, Pipe
import time
class Manager(Process):
def __init__(self, connection):
super(Process, self).__init__()
self.connection = connection
def run(self):
while True:
if self.connection.poll():
msg = self.connection.recv()
self.call_function(msg[0], msg[:])
def call_function(self, name, *args):
print('Function Called with %s' % name)
return_val = getattr(self, name)(*args)
self.connection.send(return_val)
def get_value(self, key):
return 1.0
虽然我猜这可行,但是我对这种解决方案并不满意。尤其是按字符串调用函数的方法似乎很容易出错。有没有更优雅的方法来请求在Python中执行功能?
答案 0 :(得分:0)
总的来说,我认为您的方法是一种好方法(当然,还有其他方法可以完成相同的事情,但是您的一般方法没有错)。
也就是说,我将略微更改设计以添加一个“路由”组件:考虑一些逻辑,该逻辑以某种方式限制了客户端可以发送的“命令”,并且在命令和“处理程序”之间进行了钩子-即处理他们。基本上考虑一下Web框架路由(如果您熟悉该概念)。
从设计的灵活性,错误检测和安全性方面来说,这都是一个好主意(例如,您不希望客户端在您的['__del__']
上致电Manager
在最基本的形式上,router
可以是将命令映射到类方法的字典:
class Manager(Process):
def __init__(self, connection):
super(Process, self).__init__()
self.connection = connection
self.routes = {'do_action': self._do_action,
'do_other_action': some_callable,
'ping': lambda args: args} # <- as long as it's callable and has the right signature...
def call_function(self, name, *args):
try:
handler = self.routes[name]
except KeyError:
return self._error_reply('{} is not a valid command'.format(name))
try:
return_val = handler(*args) # handler functions will need to throw something if arguments are wrong...
except ValueError as e:
return self._error_reply('Invalid command arguments: {}'.format(str(e)))
except Exception as e:
# This is your catch-all "internal server error" handler
return self._error_reply(str(e))
self.connection.send(return_val)
这当然只是方法的一个例子。您将需要以适合您的任何方式实施_error_reply()
。
您可以通过创建Router
类并将其作为依赖项传递给Manager来对其进行扩展,从而使其更加灵活。您可能还需要考虑使Manager成为独立的事物,而不是Process
的子类(因为您可能想运行它,而不管它是否在子过程中(例如在测试中))。
顺便说一句,有一些框架可以实现具有不同程度的复杂性和灵活性(Thrift,ZeroMQ等)的框架,但是如果您想做简单而又 learn 的事情,那就自己做吧我认为这是一个不错的选择。