使用Python中的套接字服务器可以使用所有属性和方法

时间:2015-01-08 00:01:37

标签: python socketserver

我使用Raspberry Pi收集传感器数据并设置数字输出,以便其他应用程序使用套接字服务器轻松设置和获取值。 但是我遇到了一些问题,找到一种优雅的方法,可以在套接字服务器上提供所有数据,而无需为每种数据类型编写函数。

我希望在套接字服务器上提供的值和方法的一些示例:

do[2].set_low()    # set digital output 2 low
do[2].value=0      # set digital output 2 low
do[2].toggle()     # toggle digital output 2
di[0].value        # read value for digital input 0
ai[0].value        # read value for analog input 0
ai[0].average      # get the average calculated value for analog input 0
ao[4].value=255    # set analog output 4 to byte value 255
ao[4].percent=100  # set analog output 4 to 100%

我已尝试eval()exec()

self.request.sendall(str.encode(str(eval('item.' + recv_string)) + '\n'))
除非我使用等号(eval()),否则

=有效,但由于涉及危险,我不会对解决方案感到满意。 exec()完成工作,但不会返回任何价值,也很危险。

我还试过getattr()

recv_string = bytes.decode(self.data).lower().split(';')
values = getattr(item, recv_string[0])
self.request.sendall(str.encode(str(values[int(recv_string[1])].value) + '\n'))
                                                                ^^^^^

这适用于获取我的属性,上面的示例适用于获取value所获得的属性的getattr()。但我也无法弄清楚如何在getattr()属性上使用value

分号(;)用于分割传入的命令,我尝试了多种格式化命令的方法:

# unit means that I want to talk to a I/O interface module,
# and the name specified which one

unit;unit_name;get;do;1
unit;unit_name;get;do[1]
unit;unit_name;do[1].value

我可以自由选择格式,因为我也在编写使用这些命令的软件。我还没有找到满足我所有需求的好格式。

有什么建议我如何写出一种优雅的方式来访问和返回上面的数据?每次将新的值类型或方法添加到I / O端口时,最好不得不向套接字服务器添加新方法。

修改:这不是公开的,只能在我的网络上使用。

1 个答案:

答案 0 :(得分:1)

建议

为您的API制作所有方法,以便始终可以使用eval:

def value_m(self, newValue=None):
    if newValue is not None:
        self.value = newValue
    return self.value

然后你可以随时

result = str(eval(message))
self.request.sendall(str.encode(result + '\n'))

对于您的message,我建议将消息格式化为完全包含命令的确切语法,以便按原样eval编辑,例如

message = 'do[1].value_m()'  # read a value, alternatively...
message = 'do[1].value_m(None)' 

或写

message = 'do[1].value_m(0)'  # write a value

这样可以很容易地使您的消息与API保持同步,因为它们必须完全匹配,您将无法处理第二个DSL。你真的不想在你的IO之上维护第二个API。

这是一个非常简单的方案,适用于家庭项目。我会在评估中建议一些错误处理,如下所示:

import traceback

try:
    result = str(eval(message))
except Exception:
    result = traceback.format_exc()
self.request.sendall(str.encode(result + '\n'))

这样,您的调用者将在返回的消息中收到异常回溯的打印输出。这将使调试不良呼叫变得更加容易。

注意如果这是面向公众的,则无法执行此操作。必须清理所有输入。您将必须解析每条指令并将其与可用(和期望)命令列表进行比较,并验证所有内容的输入有效性和有效性范围。对于这种情况,您最好只使用一个用于Web服务的输入验证系统,这个问题会得到很多关注。