如何在python的扩展类中使用dbus导出方法,继承方法?

Posted

技术标签:

【中文标题】如何在python的扩展类中使用dbus导出方法,继承方法?【英文标题】:How export methods with dbus in a extended class in python, inherited methods? 【发布时间】:2012-11-25 18:02:20 【问题描述】:

我有一个***类和扩展***类的类,但是子类的几乎所有方法都来自***类(使用继承,没有重新实现),所以我没有子类中的方法,如何为每个子类使用 dbus 导出它们(每个子类的名称作为 dbus 路径的一部分)?

我将展示一个示例代码以进行澄清,我的类结构是:

Window (main class)
  |--WindowOne (child class)
  |--WindowTwo
  |--WindowThree

我的 dbus 接口是com.example.MyInterface,我想使用:com.example.MyInterface.WindowOne 访问每个子类,对于每个子类,我想访问方法,包括从主类继承的方法,例如 @ 987654325@和com.example.MyInterface.WindowOne.destroy

在这段代码中,我用'Window'类扩展了子类'WindowOne','Window'中的方法show()destroy()没有在'WindowOne'中重新实现,但是在这段代码中我把方法show() 用来解释问题,我让代码工作的方法是这样的,我在子类中重新声明了方法show(),但这似乎很糟糕。

最大的问题可能是:有一些方法可以使用装饰器:@dbus.service.method('com.example.MyInterface.WindowOne') 用于类(在这种情况下为子类)?

测试源码:

# interface imports
from gi.repository import Gtk

# dbus imports  
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop

# Main window class
class Window(dbus.service.Object):
    def __init__(self, gladeFilePath, name):
        # ... inicialization
        self.name = name
        self.busName = dbus.service.BusName('com.example.MyInterface.', bus=dbus.SessionBus())
        dbus.service.Object.__init__(self, self.busName, '/com/example/MyInterface/' + self.name)

    def show(self):
        self.window.show_all()

    def destroy(self):
        Gtk.main_quit()


# Child window class
class WindowOne(Window):
    def __init__(self, gladeFilePath):
        Window.__init__(self, gladeFilePath, "WindowOne")

    @dbus.service.method('com.example.MyInterface.WindowOne')
    def show(self):
        self.window.show_all()


if __name__ == "__main__":
    DBusGMainLoop(set_as_default=True)

    gladeFilePath = "/etc/interface.glade"
    windowOne = WindowOne(gladeFilePath)

    Gtk.main()

【问题讨论】:

我不太擅长装饰器和dbus,但是你为什么不装饰__init__-function并使用提供给它的name呢? 可能我没看懂你的意思,但是我尝试将__init__中的那一行改成:self.busName = dbus.service.BusName('com.example.MyInterface.' + self.name, bus=dbus.SessionBus()),bus这个只是改名为bus,导出的方法需要有适当的装饰器,全名如com.example.MyInterface.WindowOneand self.name 在装饰器中不起作用:( 我发现了另一个我以前没有意识到的问题,对象com.example.MyInterface.WindowOne 将仅在此类的一个对象被实例化时可用,但这只会发生在默认窗口中,所以其他窗口在 dbus 中仍然不可用。我会想到一个更好的解决方案,欢迎任何帮助。谢谢。 我不确定您的代码在示例中是否是自包含的,所以我有点不确定如何去做,但无论如何self.busName = dbus.service.BusName('com.example.MyInterface.0'.format(self.__class__.__name__), bus=dbus.SessionBus()) 在后面附加了类名点。我不确定这是否能解决您的问题 我尝试过这样的事情,但是使用了我传递给主类的成员self.name,但这还不够,因为我发现了另一个问题,静态装饰器无法帮助生成动态生成的接口路径,所以我打开了一个正确的问题:***.com/questions/13810613/… 【参考方案1】:

经过一些实验,我意识到一些重要的东西,我以前在文档中没有找到:导出方法的路径不需要与导出对象的路径相同! 澄清:如果该方法在子类中没有重新实现(WindowOne),我不需要在子类中使用@dbus.service.method('com.example.MyInterface.WindowOne')导出,例如我只需要在主类中导出方法(Window ) 使用:@dbus.service.method('com.example.MyInterface.Window')

所以我只需要在导出***类Window的方法时使用固定路径,见下面的固定代码。

# interface imports
from gi.repository import Gtk

# dbus imports  
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop

# Main window class
class Window(dbus.service.Object):
    def __init__(self, gladeFilePath, name):
        # ... inicialization
        self.name = name
        self.busName = dbus.service.BusName('com.example.MyInterface.', bus=dbus.SessionBus())
        dbus.service.Object.__init__(self, self.busName, '/com/example/MyInterface/' + self.name)

    @dbus.service.method('com.example.MyInterface.Window')
    def show(self):
        self.window.show_all()

    @dbus.service.method('com.example.MyInterface.Window')
    def destroy(self):
        Gtk.main_quit()

    @dbus.service.method('com.example.MyInterface.Window')
    def update(self, data):
        # top class 'update' method


# Child window class
class WindowOne(Window):
    def __init__(self, gladeFilePath):
        Window.__init__(self, gladeFilePath, "WindowOne")

    @dbus.service.method('com.example.MyInterface.WindowOne')
    def update(self, data):
        # reimplementation of top class 'update' method


if __name__ == "__main__":
    DBusGMainLoop(set_as_default=True)

    gladeFilePath = "/etc/interface.glade"
    windowOne = WindowOne(gladeFilePath)

    Gtk.main()

在调用总线方法的代码中,我只是使用如下:

bus = dbus.SessionBus()
dbusWindowOne = bus.get_object('com.example.MyInterface', '/com/example/MyInterface/WindowOne')
showWindowOne = dbusWindowOne.get_dbus_method('show', 'com.example.MyInterface.Window')
updateWindowOne = dbusWindowOne.get_dbus_method('update', 'com.example.MyInterface.WindowOne')

方法show在***类Window中被调用,但在对象WindowOne子类中执行。

并且方法update在子类WindowOne中被调用,因为它是在重新实现***类方法。

【讨论】:

以上是关于如何在python的扩展类中使用dbus导出方法,继承方法?的主要内容,如果未能解决你的问题,请参考以下文章

Python Dbus:如何导出接口属性

使用 Python 注册“Hello World”DBus 服务、对象和方法

在 Gjs / Gnome Shell 中调用 DBus 方法

使用 dbus 调用 java 方法

如何导出DBUS_SESSION_BUS_ADDRESS

dbus-python 如何获得原生类型的响应?