【问题标题】:Python D-Bus: custom d-bus method name with decoratorPython D-Bus:带有装饰器的自定义 d-bus 方法名称
【发布时间】:2015-12-22 08:39:33
【问题描述】:

tl;dr

是否有任何方法可以为导出的 d-bus 方法设置一个不同于被修饰的方法名称的自定义名称?


所以这是交易:我想在 D-Bus 上注册一个具有多个接口的单个​​对象,其中所有接口都具有相同的方法(不同的实现):

/com/quaintous
|- com.quaintous.iface1
|  |- GET
|- com.quaintous.iface2
|  |- GET

如果我要使用一个表示该单个对象的类并使用 method decorator 将该类的方法导出到 d-bus,我不能有两个同名的方法(第二个会覆盖第一个一)。


示例代码(需要)

class Quaintous_DBus(dbus.service.Object):
    def __init__(self):
        bus_name = dbus.service.BusName('com.quaintous', bus=dbus.SessionBus())
        dbus.service.Object.__init__(self, bus_name, '/com/quaintous')


    @dbus.service.method('com.quaintous.iface1', name="GET")
    def get_iface1(self, args):
        # Impl

    @dbus.service.method('com.quaintous.iface2', name="GET")
    def get_iface1(self, args):
        # Impl

类似name="GET"


更新

python-debus 实际上将类方法名称与 D-Bus 方法名称进行了一对一的映射,并且由于一个类不能包含两个具有相同名称的方法,因此这似乎是不可能的。我正在考虑覆盖_method_lookup 作为最后的手段,但我希望有更好的解决方案。

【问题讨论】:

    标签: python dbus


    【解决方案1】:

    tl;dr

    不,我不相信可以使用 dbus-python 以这种方式完成,但以下是一种解决方法:


    如果要求只有一个类,这将是有问题的,因为 Python 本身不支持方法重载,因此在同一个类中不能有多个具有完全相同名称的方法。我假设用例是在不同接口下在 D-Bus 上导出的多个方法之间共享一个方法的实现?如果是这样,有一个解决方案。

    我相信您正在使用的 D-Bus 绑定 (dbus-python) 将根据在服务上调用的方法名称按名称查找方法,并将其与接口字符串匹配(如果存在这样的字符串) .

    方法查找是使用服务类的类层次结构中的类中的__dict__ 字典中的方法名称作为键来完成的。我相信,这意味着没有简单的方法可以让 dbus-python 在不改变 dbus-python 本身的情况下寻找另一种方法。然而,这意味着只需要在层次结构中的某个地方有一个类,它的方法名称正确,并用特定的接口字符串装饰。

    如果您创建一个继承层次结构,其中所有方法都出现在一个单独的类中(每个方法具有不同的接口字符串)并共享一个实现实际逻辑的父级,它似乎以您想要的方式出现在总线上。下面是一个例子:

    import gobject
    import dbus
    import dbus.service
    
    from dbus.mainloop.glib import DBusGMainLoop
    DBusGMainLoop(set_as_default=True)
    
    
    OPATH = "/temp/Test"
    IFACE = "temp.Test"
    BUS_NAME = "temp.Test"
    
    
    class Implementation(object):
        # This is the implementation shared by the methods exported on the bus
        def theX(self, arg):
            print arg
    
    
    class MyService(dbus.service.Object):
        def __init__(self):
            bus = dbus.SessionBus()
            bus.request_name(BUS_NAME, dbus.bus.NAME_FLAG_REPLACE_EXISTING)
            bus_name = dbus.service.BusName(BUS_NAME, bus=bus)
            dbus.service.Object.__init__(self, bus_name, OPATH)
    
    
    class IfaceOne(MyService, Implementation):
        def __init__(self):
            MyService.__init__(self)
    
        @dbus.service.method(dbus_interface=IFACE + ".IfaceOne", in_signature='s')
        def X(self, arg):
            super(IfaceOne, self).theX(arg)
    
    
    class IfaceTwo(IfaceOne, Implementation):
        def __init__(self):
            MyService.__init__(self)
    
        @dbus.service.method(dbus_interface=IFACE + ".IfaceTwo", in_signature='s')
        def X(self, arg):
            super(IfaceTwo, self).theX(arg)
    
    
    if __name__ == "__main__":
        iface_two = IfaceTwo()
        loop = gobject.MainLoop()
        loop.run()
    

    有关更多详细信息,您可以克隆 dbus-python git 并查看 service.py 中的 _method_lookup 方法。 method 装饰器在 decorators.py 中实现。

    希望这会有所帮助。

    【讨论】:

    • 这类似于我正在使用的解决方法,唯一的区别是我没有像Implementation 这样的东西。我只是(在你的情况下)将这些类链接在一起,以便 python 的 MRO 为我找到合适的类。我想出的另一个解决方案是覆盖 _method_lookup 并将我自己的属性添加到每个处理程序。
    • 好的,很酷。我想如果您想出相同的解决方案,我的“答案”可能对人们来说是可以接受和有用的。如果您觉得合适,请接受它。干杯!
    • 它肯定会帮助其他人。但我可能只想等待其他答案。这个解决方案是一种解决方法:-/
    • 当然。我添加了一点说明,答案主要是解决方法;)
    • 我想我的问题的答案只能是一种解决方法。
    猜你喜欢
    • 2012-09-04
    • 2010-12-01
    • 1970-01-01
    • 2014-12-14
    • 2015-08-17
    • 2011-10-29
    • 1970-01-01
    • 1970-01-01
    • 2013-07-03
    相关资源
    最近更新 更多