This tutorial requires Python 2.4 or up, and dbus-python 0.80rc4 or up.
指南需要:Python 2.4 或更高的版本, dbus-python 0,80rc4或更高的版本
Connecting to the Bus (连接Bus) Making method calls (制造一个方法调用) Proxy objects (代理对像) interfaces and methods (接口和方法) See also Data types (数据类型) Basic types (基本类型) Basic type conversions (基本类型约定) Container types (容器类型) Return values, and the byte_arrays and utf8_strings options (返回值, byte_arrays 和 utf8_strings 选项) Making asynchronous method calls (使用异步方法调用) Setting up an event loop (设置事件循环) Backwards compatibility: dbus.glib (向后兼容: dbus.glib) The Qt main loop (Qt main loop) Making asynchronous calls (创建异步调用) See also Receiving signals (接收信号) Signal matching (匹配信号) Getting more information from a signal (从信号中获取更多信息) String argument matching (匹配字符串参数) Receiviing signals from a proxy object (接收来自 proxy 对象的信号) See also Claiming a bus name (声名一个 bus name) The unique-instance idiom Exporting objects (导出对象) Inheriting from dbus.service.Object (继承 dbus.service.Object) Exporting methods with dbus.service.method (使用 dbus.service.method 导出方法) Finding out the caller's bus name Asynchronous method implementations (异步方法的实现) Emitting signals with dbus.service.signal Example License for this document
使用 D-Bus 的应用程序常常连接到一个 bus 服务上,这个服务在应用程序之间传递消息。想要使用 D-Bus ,你需要创建一个 Bus 对象来代表一个到 bus 服务的连接。
import dbus session_bus = dbus.SessionBus()
import dbus system_bus = dbus.SystemBus()
Of course, you can connect to both in the same application.
D-Bus 应用程序能够输出对象让其它应用使用。为了能够使用另一个应用程序提供的对象,你需要知道:
就像你期望的,你可以通过远程对象做的最主要的事情之一就是调用它们的方法。就像在 Python 中,方法有一些参数,它们会返回一个或多个值。
import dbus bus = dbus.SystemBus() proxy = bus.get_object('org.freedesktop.NetworkManager', '/org/freedesktop/NetworkManager/Devices/eth0') # proxy is a dbus.proxies.ProxyObject
为了调用一个方法,在 proxy object 上调用同样名称的方法,通过 dbus_interface 关键词参数传递接口的名称。
import dbus bus = dbus.SystemBus() eth0 = bus.get_object('org.freedesktop.NetworkManager', '/org/freedesktop/NetworkManager/Devices/eth0') props = eth0.getProperties(dbus_interface='org.freedesktop.NetworkManager.Devices') # props is a tuple of properties, the first of which is the object path
如果你要用同样的接口调用很多的方法,作为一个快捷的办法,你可构造一个 dbus.Interface 对像,然后在它上面调用方法,而不需要再次指定接口:
import dbus bus = dbus.SystemBus() eth0 = bus.get_object('org.freedesktop.NetworkManager', '/org/freedesktop/NetworkManager/Devices/eth0') eth0_dev_iface = dbus.Interface(eth0, dbus_interface='org.freedesktop.NetworkManager.Devices') props = eth0_dev_iface.getProperties() # props is the same as before
参考 examples/example-client.py 中的例子。在运行它之前,你需要在后台或在另一个 shell 中运行 examples/example-service.py。
不像 Python , D-Bus 是静态类型 (statically typed) - 每一个方法都有一个代表它们参数类型的标识,并且不接受其它类型的参数。
The following basic data types are supported.
Python type | converted to D-Bus type | notes |
---|---|---|
unicode or subclass | string ('s') | |
D-Bus proxy object | ObjectPath (signature 'o') | (+) |
dbus.Interface | ObjectPath (signature 'o') | (+) |
dbus.service.Object | ObjectPath (signature 'o') | (+) |
dbus.Boolean | Boolean (signature 'b') | a subcalss of int |
dbus.Byte | byte (signature 'y') | a subclass of int |
dbus.Int16 | 16-bit signed integer ('n') | a subclass of int |
dbus.Int32 | 32-bit signed integer ('i') | a subclass of int |
dbus.Int64 | 64-bit signed integer ('x') | (*) |
dbus.Uint16 | 16-bit unsigned integer ('q') | a subclass of int |
dbus.Uint32 | 32-bit unsigned integer ('u') | (*) |
dbus.Uint64 | 64-bit unsigned integer ('t') | (*) |
dbus.Double | double-precision float ('d') | a subclass of float |
dbus.ObjectPath | object path ('o') | a subclass of str |
dbus.Signature | signature ('g') | a subclass of str |
dbus.String | string ('s') | a subclass of unicode |
dbus.UTF*String | string ('s') | a subclass of str |
bool | Boolean ('b') | |
int or subclass | 32-bit signed inter ('i') | |
long or subclass | 64-bit signed integer ('x') | |
float or subclass | double-precision float ('d') | |
str or subclass | string ('s') | must be valid UTF-8 |
Types marked (*
) may be a subclass of either int or long, depending on platform.
标记为(*
)的类型是 int 或 long 的子类,平台相关。
If introspection succeeded, dbus-python will also accept:
如果 introspection 成功, dbus-python 将接受:
一个数组的标识是 'ax' ,这里的 'x' 代表一个元素的标识。例如,你可以使用 'as' (字符串数组) 或 'a(ii)' (包含两个 32-bit 整数的结构体数组)
dbus.ByteArray是一个字符字符串的子类,被用开更有效率的代表 D-Bus的字节数组 (标识 'ay')。
由内容的标识的构成的结构体的标识在括号里 - 例如, '(is)' 是一个包含一个 32-bit 整数和字符串的标识。
变体 (variants) ... (不会翻)。如果 non-variant 作为一个参数被传递,但 introspection 指示期望一个 variant ,它将会自动的包在一个变体中。
The signature of a variant is 'v'.
If a D-Bus method returns no value, the Python proxy method will return None.
如果 D-Bus 方法没有返回值,那么 Python 代理方法将会返回 None.
如果 D-Bus 方法返回多个值,那么 Python 代理方法会返回一个元组包含这些值。
如果你想要字符串作为 dbus.UTF8String (str 的子类) 传递关键词参数 utf8_strings=True 到代理方法。
如果你要字节数组作为 dbus.ByteArray (也是 str 的子类 - 实践中,它常常是你想要的)传递关键词参数 byte_arrays=True 到代理方法。
异步(非阻塞)方法调用允许同时有多个方法正在调用,允许你的应用在等待结果的时候可以做一些其它的工作。为了使用异步调用,你首先需要一个事件循环或 "main loop"。
Currently, the only main loop supported by dbus-python is GLib.
目前,dbus-python 唯一支持的 main loop 是 GLib 。
dbus-python 有一个全局默认的 main loop ,它是使用这个功能最容易的方法。把 GLib main loop 设置为默认,使用:
from dbus.mainloop.glib import DBusGMainLoop DBusGMainLoop(set_as_default=True)
You must do this before connecting to the bus.
Actually starting the main loop is as usual for pygobject:
实际上常常为 pygobject 启动 main loop。
import gobject loop = gobject.MainLoop() loop.run()
当 loop.run() 在运行, GLib 将会在适当的时候运行你的回调函数。调用 loop.quit() 停止。
你可以在每一个连接的基础上设置一个 main loop,通过传递一个 main loop 到 Bus 构造函数。
import dbus from dbus.mainloop.glib import DBusGMainLoop dbus_loop = DBusGMainLoop() bus = dbus.SessionBus(mainloop=dbus_loop)
This isn't very useful until we support more than one main loop, though.
In versions of dbus-python prior to 0.80, the way to set GLib as the default main loop was:
在 dbus-python 0.80 之前的版本里,设置 GLib 作为默认 main loop 的方法是:
执行那个 import 语句将会自动的加载 GLib main loop 并设置它为默认。不赞成使用它,因为它是高不可见的,但是如果你想写或者理解向后兼容的代码是有用的。
为了收到一个信号,Bus 需要被连接到一个事件循环 - 参考设置事件循环那章。信号只在事件循环运行的时候才能收到。
为了对信息产生响应,你要在 Bus object 上使用 add_signal_receiver 方法。当一个匹配的信号收到后,安排好的回调函数将被调用,传入以后参数:
add_signal_receiver 返回一个 SignalMatch 对像。目前,它唯一有用的公共 API 是一个没有参数移除方法,它用来移除从连接上匹配的连接。
一个来自 com.example.Foo 的没有参数的 Hello 信号将会被收到,处理函数将会被调用,它的参数 sender='com.example.Foo'。
如果有关键词的格式是 argn,其中 n 是一个小的非负数,它们的值必须是 unicode 对象 或 UTF-8 字符串。(后面理不清)
Proxy 对象有一个特殊的方法 connect_to_signal ,当收到一个来自相应远程对象的信号时, connect_to_signal 将安排一个回调函数被调用。
dbus.Interface 对象有一个相似的 connect_to_signal 方法,但这种情况下,你不需要 dbus_interface 关键词参数,因为使用的接口已经知道了。
对于 add_signal_receiver 而言,同样的关键词参数也是可用的,就像 add_signal_receiver , 它返回一个 SignalMatch 。
你不应该只用 proxy 对象来监听信号,因为当他们创建的时候也许会激活相关的服务,但如果你为了调用方法已经有一个 proxy 对象,使用它添加信号匹配常常很方便。
FIXME describe BusName - perhaps fix its API first?
FIXME provide exemplary code, put it in examples
在 D-Bus 上让另外一个应用程序可用的对像称作导出 (exported)。所有的 dbus.service.Object 的子类是自动被 exported。
为了 export 对象, Bus 需要连接到事件循环 - 参考设置事件循环那章。只有在事件循环运行时,导出方法也才会被调用,队列中的信号才会被传递。
这个对象会自动支持 introspection ,但不做任何特别的事情。为了修正它,你需要导出一些方法和信号。
FIXME also mention dbus.gobject.ExportedGObject once I've written it
To export a method, use the decorator dbus.service.method. For example:
为了导出方法,使用 dbus.service.method 操作,例如:
The in_signature and out_signature are D-Bus signature strings as described in Data Types.
in_signature 和 out_signature 是 D-Bus 的标识字符串,描述数据的类型。
你可以找到一个简单的例子 examples/example-service.py ,我们先前用来它来示范 examples/example-client.py 。
方法描述接受 sender_keyword 关键词参数。如果你把它设置为一个字符串,发送者的唯一 bus 名称将作为一个关键词参数传递到描述方法。
FIXME and also add an example, perhaps examples/example-async-service.py
当发送信号的方法之一被调用, examples/example-signal-emitter.py 会按要求发送一些信号。