我正在使用pydbus,我已经成功地使用它来监听会话总线上的信号(在"客户端")。我现在想编写服务器端,程序在每次触发操作时发送信号(例如,当它在FS上写入文件时)。我不能在他们的GitHub上得到任何关于它的例子。他们只展示如何编写一个基本服务器,它有一堆客户端可以调用的方法(但它不是我想要的信号)。
仅供参考,客户端非常简单,看起来像这样:
# Subscribe to DBus dump signal
session_bus = SessionBus()
session_bus.subscribe(iface='my.iface',
signal='my_signal_name',
object='/my/object',
signal_fired=my_callback)
# Create and run main loop
loop = GObject.MainLoop()
loop.run()
其中my_callback
是每次被监听事件弹出时调用的方法(在这种情况下为my_signal_name
)
寻求帮助。
答案 0 :(得分:2)
以下python3 / pydbus程序将每秒在会话D-Bus上发布一个随机整数。
#!/usr/bin/env python3
#!
from pydbus.generic import signal
from pydbus import SessionBus
from gi.repository import GLib
import random
loop = GLib.MainLoop()
interface_name = "org.example.project_1.server_1"
bus = SessionBus()
class Server_XML(object):
"""
Server_XML definition.
Emit / Publish a signal that is a random integer every second
type='i' for integer.
"""
dbus = """
<node>
<interface name="org.example.project_1.server_1">
<signal name="app_1_signal">
<arg type='i'/>
</signal>
</interface>
</node>
"""
app_1_signal = signal()
def repeating_timer():
"""Generate random integer between 0 and 100 and emit over Session D-Bus
return True to keep the GLib timer calling this function once a second."""
random_integer = random.randint(0,100)
print(random_integer)
emit.app_1_signal(random_integer)
return True
if __name__=="__main__":
# Setup server to emit signals over the DBus
emit = Server_XML()
bus.publish(interface_name, emit)
# Setup repeating timer
GLib.timeout_add_seconds(interval=1, function=repeating_timer)
# Run loop with graceful ctrl C exiting.
try:
loop.run()
except KeyboardInterrupt as e:
loop.quit()
print("\nExit by Control C")
打开另一个linux控制台终端并使用gdbus实用程序验证会话总线上是否正在发布整数。例如......
$ gdbus monitor --session --dest org.example.project_1.server_1
Monitoring signals from all objects owned by org.example.project_1.server_1
The name org.example.project_1.server_1 is owned by :1.618
/org/example/project_1/server_1: org.example.project_1.server_1.app_1_signal (36,)
/org/example/project_1/server_1: org.example.project_1.server_1.app_1_signal (37,)
/org/example/project_1/server_1: org.example.project_1.server_1.app_1_signal (25,)
以下python3 / pydbus客户端程序订阅在会话D-Bus上发布的随机整数......
#!/usr/bin/env python3
#!
from pydbus.generic import signal
from pydbus import SessionBus
from gi.repository import GLib
loop = GLib.MainLoop()
dbus_filter = "/org/example/project_1/server_1"
bus = SessionBus()
def cb_server_signal_emission(*args):
"""
Callback on emitting signal from server
"""
print("Message: ", args)
print("Data: ", str(args[4][0]))
if __name__=="__main__":
# Subscribe to bus to monitor for server signal emissions
bus.subscribe(object = dbus_filter,
signal_fired = cb_server_signal_emission)
loop.run()
此客户端程序的控制台输出将类似于此...
$ python3 client_pydbus.py
Message: (':1.621', '/org/example/project_1/server_1', 'org.example.project_1.server_1', 'app_1_signal', (72,))
Data: 72
Message: (':1.621', '/org/example/project_1/server_1', 'org.example.project_1.server_1', 'app_1_signal', (46,))
Data: 46
Message: (':1.621', '/org/example/project_1/server_1', 'org.example.project_1.server_1', 'app_1_signal', (47,))
Data: 47
答案 1 :(得分:0)
负责信号的类位于generic模块中。它看起来很好,记录在案:
Static signal object
You're expected to set it as a class property::
class A:
SomethingHappened = signal()
Declared this way, it can be used on class instances
to connect signal observers::
a = A()
a.SomethingHappened.connect(func)
and emit the signal::
a.SomethingHappened()
You may pass any parameters to the emiting function
- they will be forwarded to all subscribed callbacks.
还有example in the tutorial使用信号。请注意最后一行和属性SomeProperty
。当在setter中更改python属性SomeProperty
时,信号将通过self.PropertiesChanged("net.lew21.pydbus.TutorialExample", {"SomeProperty": self.SomeProperty}, [])
发出。
from pydbus.generic import signal
class Example(object):
"""
<node>
<interface name='net.lew21.pydbus.TutorialExample'>
<method name='EchoString'>
<arg type='s' name='a' direction='in'/>
<arg type='s' name='response' direction='out'/>
</method>
<property name="SomeProperty" type="s" access="readwrite">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
</property>
</interface>
</node>
"""
def EchoString(self, s):
"""returns whatever is passed to it"""
return s
def __init__(self):
self._someProperty = "initial value"
@property
def SomeProperty(self):
return self._someProperty
@SomeProperty.setter
def SomeProperty(self, value):
self._someProperty = value
self.PropertiesChanged("net.lew21.pydbus.TutorialExample", {"SomeProperty": self.SomeProperty}, [])
PropertiesChanged = signal()
还有notification_server example使用信号(但未调用)。