dbus-python 指南

dbus-python 指南

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

Connecting to the Bus (連接Bus)

Applications that use D-Bus typically connect to a bus daemon, which forwards messages between the applications. To use D-Bus, you need to create a Bus object representing the connection to the bus daemon.

使用 D-Bus 的應用程式常常連接到一個 bus 服務上,這個服務在應用程式之間傳遞消息。想要使用 D-Bus ,你需要創建一個 Bus 對象來代表一個到 bus 服務的連接。

There are generally two bus daemons you may be interested in. Each user login session shouldhave a session bus, which is local to that session. It's used to communicate between desktop applications. Connect to the session bus by creating a SessionBus object:

一般你會對兩個 bus 服務感興趣。第一個用戶會話 (user login session) 應該有一個會話 bus (session bus)。以那個會話 (session) 來看 session bus 是本地的。想要連接到一個 session bus 可以通過創建一個 SessionBus 對象:

    import dbus     session_bus = dbus.SessionBus()

The System bus is global and usually started during boot; it's used to communicate with system services like udev, NetworkManager, and the Hardware Abstraction Layer daemon (hald). To connect to the system bus, create a Systembus object:

系統 bus 是全局的,常常在啟動 (boot) 的時候運行;它用來與系統服務傳遞資訊,如 udev, NetworkManager 和 the Hardware Abstraction Layer daemon (hald)。想要連接到一個 system bus 可以通過創建一個 SystemBus 對象:

    import dbus     system_bus = dbus.SystemBus()

Of course, you can connect to both in the same application.

當然,你可以在同一個應用程式里同時連接兩個 bus。

For special purposes, you might use a non-default Bus, or a connection which isn't a Bus at all, using some new API added in dbus-python 0.81.0. This is not described here, and will at some stage be the subject of a separate tutorial.

為了達到特殊的目的,你也許要用到非默認的 Bus (non-default Bus), 或者根本不是一個 Bus 連接,那麼就使用添加到 dbus-python 0,81.0 中的新的API。它不會出現在這裡,可能會出現在其它主題的某些階段。

Making method calls (製造一個方法調用)

D-Bus applications can export objects for other applications'use . To start working with an object in another application, you need to know:

D-Bus 應用程式能夠輸出對象讓其它應用使用。為了能夠使用另一個應用程式提供的對象,你需要知道:

As you'd expect, one of the main thing you can do with remote objects is to call their methods. As in Python, methods may have parameters, and they may return one or more values.

就像你期望的,你可以通過遠程對象做的最主要的事情之一就是調用它們的方法。就像在 Python 中,方法有一些參數,它們會返回一個或多個值。

Proxy objects (代理對像)

To interact with a remote object, you use a proxy object. This is a Python object which acts as a proxy or "stand-in" for the remote object – when you call a method on a proxy object, this causes dbus-python to make a method call on the remote object, passing back any return values from the remote object's method as the return values of the proxy method call.

為了與一個遠程對象 (remote object) 通訊,你需要使用代理對象 (proxy object)。它是一個行為像代理人一樣的 Python 對像,或者說就是 remote object 的標準輸入 – 當你通過 proxy object 調用一個方法時,結果, dbus-python 在 remote object 上創建了一個方法調用來, 傳回任何中從 remote object 的方法返回的值就像代理方法調用的返回值一樣。 (這一段翻譯的很爛-_-b)

To obtain a proxy object, call the get_object method on the Bus. For example, NetworkManager has the well-known name org.freedesktop.NetworkManager and exports an object whose object path is /org/freedesktop/NetworkManager, plus an object per network interface at object paths like /org/freedesktop/NetworkManager/Devices/eth0. You can get a proxy for the object representing eth0 like this:

為了獲取一個 proxy object,需要在 Bus 上調用 get_object 方法。例如,NetworkManager 擁有一個 well-known name org.freedesktop.NewworkManager 和 輸出的路徑為 /org/freedesktop/NetworkManager 的對象。還為每一個網路介面,如 /org/freedesktop/NetworkManager/Devices/eth0 ,都添加了一個對象。你可以取得一個代表eth0 的 proxy object ,操作如下:

    import dbus     bus = dbus.SystemBus()     proxy = bus.get_object('org.freedesktop.NetworkManager',                             '/org/freedesktop/NetworkManager/Devices/eth0')     # proxy is a dbus.proxies.ProxyObject

interfaces and methods (介面和方法)

D-Bus uses interfaces to provide a namespacing mechanism for methods. An interface is a group of related methods and signals (more on signals later), identified by a name which is a series of dot-separated components starting with a reversed domain name. For instance, each NetworkManager object representing a network interface implements the interface org.freedesktop.NetworkManager.Devices, which has methods like getProperties.

D-Bus 使用介面來為方法提供命名空間的機制。一個介面是相關方法和訊號 (後來更多在訊號上) 的集合,這個集合的名稱是由一系列的點分元素構成,並且它們是域名的反轉。例如,每一個 NetworkManager 代表一個網路介面的對象實現為 org.freedesktop.NetworkManager.Devices,它們擁有方法 getProperties。

To call a method, call the method of the same name on the proxy object, passing in the interface name via the dbus_interface keyword argument:

為了調用一個方法,在 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

As a short cut, if you're going to be calling many methods with the same interface, you can construct a dbus.Interface object and call methods on that, without needing to specify the interface again:

如果你要用同樣的介面調用很多的方法,作為一個快捷的辦法,你可構造一個 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

See also

See the example in examples/example-client.py. Before running it, you'll need to run examples/example-service.py in the background or in another shell.

參考 examples/example-client.py 中的例子。在運行它之前,你需要在後台或在另一個 shell 中運行 examples/example-service.py。

Data types (數據類型)

Unlike Python, D-Bus is statically typed – each method has a certain signature representing the types of its arguments, and will not accept arguments of other types.

不像 Python , D-Bus 是靜態類型 (statically typed) – 每一個方法都有一個代表它們參數類型的標識,並且不接受其它類型的參數。

D-Bus has an introspection mechanism, which dbus-python tries to use to discover the correct argument types. If this succeeds, Python types are converted into the right D-Bus data types automatically, if possible; TypeError is raised if the type is inappropriate.

D-Bus 有一個內省 (introspections) 機省,dbus-python 使用它來發現正確的參數類型。如果內省 (introspections) 成功,Python 類型會被自動的轉化成正確的 D-Bus 數據類型,如果可能的話。

If the introspection mechanism fails (or the argument's type is variant – see below), you have to provide arguments of the correct type. dbus-python provides Python types corresponding to the D-Bus data types, and a few native Python types are also converted to D-Bus data types automatically. If you use a type which isn't among these, a TypeError will be raised telling you that dbus-python was unable to guess the D-Bus signature.

如果 introspections 失敗 (或者參數的類行是可變的 – 參考下面),你將不得不提供正確的類型。 dbus-python 提供 Python 類型相當 D-Bus 數據類型,一些天生的 Python 類型也可以自動的轉換為 D-Bus 類型。 如果你使用的類型不在其中,一個 TypeError 將會出現來告訴你, dbus-python 不能猜出 D-Bus 的標識。

Basic types (基本類型)

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 的子類,平台相關。

(+): D-Bus proxy objects, exported D-Bus service objects and anything else with the special attribute __dbus_object_path__, which must be a string, are converted to their object-path. This might be useful if you're writing an object-oriented API using dbus-python.

Basic type conversions (基本類型約定)

If introspection succeeded, dbus-python will also accept:

如果 introspection 成功, dbus-python 將接受:

Container types (容器類型)

D-Bus supports four container types: array (a variable-length sequence of the same type), struct (a fixed-length sequence whose members may have different types), dictionary (a mapping from values of the same basic type to values of the same type), and variant (a container which may hold any D-Bus type, including another variant).

D-Bus 支援四種容器類型:數組 (同一類型的可變長隊列),結構 (一個擁有不同成員類型的定長隊列),字典 (從同一 基礎 類型的值開到同一類型的值的映射)和變體 (variant) (可以存儲任意 D-Bus 類型,包括 variant 自身)

Arrays are represented by Python lists, or by dbus.Array, a subclass of list. When sending an array, if an introspected signature is available, that will be used; otherwise, if the signature keyword parameter was passed to the Array constructor, that will be used to determine the contents' signature; otherwise, dbus-python will guess from the array's first item.

數組可以由 Python lists, 或 dbus.Array (a subclass of list) 表示。當發送一個數組,如果 introspected 標識是可用的,它將會被使用;如果標識關鍵參數是傳遞給數組構造函數,那麼它將被用來決定內容的的標識;否則, dubs-python 將會從數組的第一項猜測。

The signature of an array is 'ax' where 'x' represents the signature of one item. For instance, you could also have 'as' (array of strings) or 'a(ii)' (array of structs each containing two 32-bit integers).

一個數組的標識是 'ax' ,這裡的 'x' 代表一個元素的標識。例如,你可以使用 'as' (字元串數組) 或 'a(ii)' (包含兩個 32-bit 整數的結構體數組)

There's also a type dbus.ByteArray which is a subclass of str, used as a more efficient representation of a D-Bus array of bytes (signature 'ay').

dbus.ByteArray是一個字元字元串的子類,被用開更有效率的代表 D-Bus的位元組數組 (標識 'ay')。

Structs are represented by Python tuples, or by dbus.Struct, a subclass of tuple. When sending a struct, if an introspected signature is available, that will be used; otherwise, if the signature keyword parameter was passed to the Array constructor, that will be used to determine the contents' signature; otherwise, dbus-python will guess from the array's first item.

結構使用 Python 的元組 (tuples),或 dbus.Struct (元組的子類)表示。當傳遞一個結構體時,如果 introspected 標識是可用的,它將會被使用;如果標識關鍵參數是傳遞給數組構造函數,那麼它將被用來決定內容的的標識;否則, dubs-python 將會從數組的第一項猜測。

The signature of a struct consists of the signatures of the contents, in parentheses – for instance '(is)' is the signature of a struct containing a 32-bit integer and a string.

由內容的標識的構成的結構體的標識在括弧里 – 例如, '(is)' 是一個包含一個 32-bit 整數和字元串的標識。

Dictionaries are represented by Python dictionaries, or by dbus.Dictionary, a subclass of dict. When sending a dictionary, if an introspected signature is available, that will be used; otherwise, if the signature keyword parameter was passed to the Dictionary constructor, that will be used to determine the contents' key and value signatures; otherwise, dbus-python will guess from an arbitrary item of the dict.

字典由 Python 字典或 dbus.Dictionary (dict 的子類)表示。當傳遞一個字典時,如果 introspected 標識是可用的,它將會被使用;如果標識關鍵參數是傳遞給字典構造函數,那麼它將被用來決定內容的鍵值標識;否則, dubs-python 將會從字典的任意元素進行猜測。

The signature of a dictionary is 'a{xy}' where 'x' represents the signature of the keys (which may not be a container type) and 'y' represents the signature of the values. For instance, 'a{s(ii)}' is a dictionary where the keys are strings and the values are structs containing two 32-bit integers.

字典的標識是 'a{xy}' 這裡的 'x' 代表鍵的標識 (它不能是一個容器), 'y' 代表值的標識。例如, 'a{s(ii)}' 是一個字典,它的鍵是字元串,值是包含兩個 32-bit 整數的結構體。

Variants are represented by setting the variant_level keyword argument in the constructor of any D-Bus data type to a value greater than 0 (variant_level 1 means a variant containing some other data type, variant_level 2 means a variant containing a variant containing some other data type, and so on). If a non-variant is passed as an argument but introspection indicates that a variant is expected, it'll automatically be wrapped in a variant.

變體 (variants) … (不會翻)。如果 non-variant 作為一個參數被傳遞,但 introspection 指示期望一個 variant ,它將會自動的包在一個變體中。

The signature of a variant is 'v'.

variant 的標識是 'v'。

Return values, and the byte_arrays and utf8_strings options (返回值, byte_arrays 和 utf8_strings 選項)

If a D-Bus method returns no value, the Python proxy method will return None.

如果 D-Bus 方法沒有返回值,那麼 Python 代理方法將會返回 None.

If a D-Bus method returns one value, the Python proxy method will return that value as one of the dbus. types – by default, strings are returned as dbus.String (a subclass of Unicode) and byte arrays are returned as a dbus.Array of dbus.Byte.

如果 D-Bus 方法返回一個值,那麼 Python 代理方法將會以 dbus.types 之一返回那個值 – 默認情況下,字元串作為 dbus.String (Unicode 的子類),位元組數組作為 dbus.Array of dbus.Byte 。

If a D-Bus method returns multiple values, the Python proxy method will return a tuple containing those values.

如果 D-Bus 方法返回多個值,那麼 Python 代理方法會返回一個元組包含這些值。

If you want strings returned as dbus.UTF8String (a subclass of str) pass the keyword parameter utf8_strings=True to the proxy method.

如果你想要字元串作為 dbus.UTF8String (str 的子類) 傳遞關鍵詞參數 utf8_strings=True 到代理方法。

If you want byte arrays returned as dbus.ByteArray (also a subclass of str – in practice, this is often what you want) pass the keyword parameter byte_arrays=True to the proxy method.

如果你要位元組數組作為 dbus.ByteArray (也是 str 的子類 – 實踐中,它常常是你想要的)傳遞關鍵詞參數 byte_arrays=True 到代理方法。

Making asynchronous method calls (使用非同步方法調用)

Asynchronous (non-blocking) method calls allow multiple method calls to be in progress simultaneously, and allow your application to do other work while it's waiting for the results. To make asynchronous calls, you first need an event loop or "main loop".

非同步(非阻塞)方法調用允許同時有多個方法正在調用,允許你的應用在等待結果的時候可以做一些其它的工作。為了使用非同步調用,你首先需要一個事件循環或 "main loop"。

Setting up an event loop (設置事件循環)

Currently, the only main loop supported by dbus-python is GLib.

目前,dbus-python 唯一支援的 main loop 是 GLib 。

dbus-python has a global default main loop, which is the easiest way to use this functionality. To arrange for the GLib main loop to be the default, use:

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.

你必須要連接 bus 之前做些工作。

Actually starting the main loop is as usual for pygobject:

實際上常常為 pygobject 啟動 main loop。

import gobject loop = gobject.MainLoop() loop.run()

While loop.run() is executing, GLib will run your callbacks when appropriate. To stop, call loop.quit().

當 loop.run() 在運行, GLib 將會在適當的時候運行你的回調函數。調用 loop.quit() 停止。

You can also set a main loop on a per-connection basis, by passing a main loop to the Bus constructor:

你可以在每一個連接的基礎上設置一個 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.

這不是非常有用,除非我們支援多個 main loop 。

Backwards compatibility: dbus.glib (向後兼容: dbus.glib)

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 dbus.glib

Executing that import statement would automatically load the GLib main loop and make this the default. This is now deprecated, since it's highly non-obvious, but may be useful if you want to write or understand backwards-compatible code.

執行那個 import 語句將會自動的載入 GLib main loop 並設置它為默認。不贊成使用它,因為它是高不可見的,但是如果你想寫或者理解向後兼容的程式碼是有用的。

The Qt main loop (Qt main loop)

PyQt v4.2 and later includes support for integrating dbus-python with the Qt event loop. To connect D-Bus to this main loop, call dbus.mainloop.qt.DBusQtMainLoop instead of dbus.mainloop.glib.DBusGMainLoop. Otherwise the Qt loop is used in exactly the same way as the GLib loop.

PyQt v4.2 或更新的版本支援 Qt 事情循環。調用 dbus.mainloop.qt.DbusQtMainLoop 代替 dbus.mainloop.glib.DBusGMainLoop 來連接 D-Bus。否則 Qt loop 的使用將與 GLib loop 完全相同。

Making asynchronous calls (創建非同步調用)

To make a call asynchronous, pass two callables as keyword arguments reply_handler and error_handler to the proxy method. The proxy method will immediately return None. At some later time, when the event loop is running, one of these will happen: either

通過傳遞兩個可調用 (callables) 的關鍵詞參數 reply_handler 和 error_handler 到 proxy method 來生成一個非同步調用。proxy method 將會立即返回 None。一段時間後,當事件循環執行時,它們中的一個將會發生:

See also

examples/example-async-client.py makes asynchronous method calls to the service provided by examples/example-service.py which return either a value or an exception. As for examples/example-client.py, you need to run examples/example-service.py in the background or in another shell first.

examples/example-async-client.py 製作非同步方法調用 example-service.py 提供的服務,這個方法返回一值或一個異常。就像 examples/example-client.py,你需要先在後台或另一個 shell 中運行 examples/example-service.py。

Receiving signals (接收訊號)

To receive signals, the Bus needs to be connected to an event loop – see section Setting up an event loop. Signals will only be received while the event loop is running.

為了收到一個訊號,Bus 需要被連接到一個事件循環 – 參考設置事件循環那章。訊號只在事件循環運行的時候才能收到。

Signal matching (匹配訊號)

To respond to signals, you can use the add_signal_receiver method on Bus objects. This arranges for a callback to be called when a matching signal is received, and has the following arguments:

為了對資訊產生響應,你要在 Bus object 上使用 add_signal_receiver 方法。當一個匹配的訊號收到後,安排好的回調函數將被調用,傳入以後參數:

add_signal_receiver also has keyword arguments utf8_strings and byte_arrays which influence the types used when calling the handler function, in the same way as the byte_arrays and utf8_strings options on proxy methods.

add_signal_receiver 也有關鍵詞參數 utf8_strings 和 byte_arrays,當調用 handler fucntion時,它們影響使用的類型。影響的方式與 byte_arrays 和 utf8_strings 選項在 proxy method 上相同。

add_signal_receiver returns a SignalMatch object. Its only useful public API at the moment is a remove method with no arguments, which removes the signal match from the connection.

add_signal_receiver 返回一個 SignalMatch 對像。目前,它唯一有用的公共 API 是一個沒有參數移除方法,它用來移除從連接上匹配的連接。

Getting more information from a signal (從訊號中獲取更多資訊)

You can also arrange for more information to be passed to the handler function. If you pass the keyword arguments sender_keyword, destination_keyword, interface_keyword, member_keyword or path_keyword to the connect_to_signal method, the appropriate part of the signal message will be passed to the handler function as a keyword argument: for instance if you use

你也可以安排更多的資訊傳遞給處理函數。如果你傳遞了關鍵詞參數 sender_keyword, destination_keyword, interface_keyword, member_keyword 或 path_keyword 到 connect_to_signal 方法,訊號消息適當的部分將會作為關鍵詞參數被傳遞給處理函數:例如,如果你

def handler(sender=None):      print "got signal from %r" % sender    iface.connect_to_signal("Hello", handler, sender_keyword='sender')

and a signal Hello with no arguments is received from com.example.Foo, the handler function will be called with sender='com.example.Foo'.

一個來自 com.example.Foo 的沒有參數的 Hello 訊號將會被收到,處理函數將會被調用,它的參數 sender='com.example.Foo'。

String argument matching (匹配字元串參數)

If there are keyword parameters for the form argn where n is a small non-negative number, their values must be unicode objects or UTF-8 strings. The handler will only be called if that argument of the signal (numbered from zero) is a D-Bus string (in particular, not an object-path or a signature) with that value.

如果有關鍵詞的格式是 argn,其中 n 是一個小的非負數,它們的值必須是 unicode 對象 或 UTF-8 字元串。(後面理不清)

Receiviing signals from a proxy object (接收來自 proxy 對象的訊號)

Proxy objects have a special method connect_to_signal which arranges for a callback to be called when a signal is received from the corresponding remote object. The parameters are:

Proxy 對象有一個特殊的方法 connect_to_signal ,當收到一個來自相應遠程對象的訊號時, connect_to_signal 將安排一個回調函數被調用。

dbus.Interface objects have a similar connect_to_signal method, but in this case you don't need the dbus_interface keyword argument since the interface to use is already known.

dbus.Interface 對象有一個相似的 connect_to_signal 方法,但這種情況下,你不需要 dbus_interface 關鍵詞參數,因為使用的介面已經知道了。

The same extra keyword arguments as for add_signal_receiver are also available, and just like add_signal_receiver, it returns a SignalMatch.

對於 add_signal_receiver 而言,同樣的關鍵詞參數也是可用的,就像 add_signal_receiver , 它返回一個 SignalMatch 。

You shouldn't use proxy objects just to listen to signals, since they might activate the relevant service when created, but if you already have a proxy object in order to call methods, it's often convenient to use it to add signal matches too.

你不應該只用 proxy 對象來監聽訊號,因為當他們創建的時候也許會激活相關的服務,但如果你為了調用方法已經有一個 proxy 對象,使用它添加訊號匹配常常很方便。

See also

examples/signal-recipient.py receives signals – it demonstrates general signal matching as well as connect_to_signal. Before running it, you'll need to run examples/signal-emitter.py in the background or in another shell.

examples/signal-recipient.py 接收訊號 – 它示範了通用訊號的匹配以及 connect_to_signal 。你需要先在後台或另一個 shell 中運行 examples/signal-emitter.py。

Claiming a bus name (聲名一個 bus name)

FIXME describe BusName – perhaps fix its API first?

The unique-instance idiom

FIXME provide exemplary code, put it in examples

Exporting objects (導出對象)

Objects made available to other applications over D-Bus are said to be exported. All subclasses of dbus.service.Object are automatically exported.

在 D-Bus 上讓另外一個應用程式可用的對像稱作導出 (exported)。所有的 dbus.service.Object 的子類是自動被 exported。

To export objects, the Bus needs to be connected to an event loop – see section Setting up an event loop. Exported methods will only be called, and queued signals will only be sent, while the event loop is running.

為了 export 對象, Bus 需要連接到事件循環 – 參考設置事件循環那章。只有在事件循環運行時,導出方法也才會被調用,隊列中的訊號才會被傳遞。

Inheriting from dbus.service.Object (繼承 dbus.service.Object)

To export an object onto the Bus, just subclass dbus.service.Object. Object expects either a BusName or a Bus object, and an object-path, to be passed to its constructor: arrange for this information to be available. For example:

在 Bus 導出一個對象,它僅是 dbus.service.Object 的子集。這個對象期待一個 BusName 或 Bus 對象以及 object-path ,來傳遞給它的構造函數:為這些要使用的資訊做準備。例如:

class Example(dbus.service.Object):      def __init__(self, object_path):          dbus.service.Object.__init__(self, dbus.SessionBus(), path)

This object will automatically support introspection, but won't do anything particularly interesting. To fix that, you'll need to export some methods and signals too.

這個對象會自動支援 introspection ,但不做任何特別的事情。為了修正它,你需要導出一些方法和訊號。

FIXME also mention dbus.gobject.ExportedGObject once I've written it

Exporting methods with dbus.service.method (使用 dbus.service.method 導出方法)

To export a method, use the decorator dbus.service.method. For example:

為了導出方法,使用 dbus.service.method 操作,例如:

class Example(dbus.service.Object):      def __init__(self, object_path):          dbus.service.Object.__init__(self, dbus.SessionBus(), path)        @dbus.service.method(dbus_interface='com.example.Sample',                           in_signature='v', out_signature='s')      def StringifyVariant(self, variant):          return str(variant)

The in_signature and out_signature are D-Bus signature strings as described in Data Types.

in_signature 和 out_signature 是 D-Bus 的標識字元串,描述數據的類型。

As well as the keywords shown, you can pass utf8_strings and byte_arrays keyword arguments, which influence the types which will be passed to the decorated method when it's called via D-Bus, in the same way that the byte_arrays and utf8_strings options affect the return value of a proxy method.

像關鍵詞顯示的,你可以傳遞 utf8_string 和 byte_arrays 關鍵詞參數,當你通過 D-Bus 調用方法時,它將影響傳遞參數的類型。 byte_arrays 和 utf8_strings 選項以同樣的方式影響返回值。

You can find a simple example in examples/example-service.py, which we used earlier to demonstrate examples/example-client.py.

你可以找到一個簡單的例子 examples/example-service.py ,我們先前用來它來示範 examples/example-client.py 。

Finding out the caller's bus name

The method decorator accepts a sender_keyword keyword argument. If you set that to a string, the unique bus name of the sender will be passed to the decorated method as a keyword argument of that name:

方法描述接受 sender_keyword 關鍵詞參數。如果你把它設置為一個字元串,發送者的唯一 bus 名稱將作為一個關鍵詞參數傳遞到描述方法。

class Example(dbus.service.Object):      def __init__(self, object_path):          dbus.service.Object.__init__(self, dbus.SessionBus(), path)        @dbus.service.method(dbus_interface='com.example.Sample',                           in_signature='', out_signature='s',                           sender_keyword='sender')      def SayHello(self, sender=None):          return 'Hello, %s!' % sender          # -> something like 'Hello, :1.1!'

Asynchronous method implementations (非同步方法的實現)

FIXME and also add an example, perhaps examples/example-async-service.py

Emitting signals with dbus.service.signal

To export a signal, use the decorator dbus.service.signal; to emit that signal, call the decorated method. The decorated method can also contain code which will be run when called, as usual. For example:

class Example(dbus.service.Object):      def __init__(self, object_path):          dbus.service.Object.__init__(self, dbus.SessionBus(), path)        @dbus.service.signal(dbus_interface='com.example.Sample',                           signature='us')      def NumberOfBottlesChanged(self, number, contents):          print "%d bottles of %s on the wall" % (number, contents)    e = Example('/bottle-counter')  e.NumberOfBottlesChanged(100, 'beer')  # -> emits com.example.Sample.NumberOfBottlesChanged(100, 'beer')  #    and prints "100 bottles of beer on the wall"

The signal will be queued for sending when the decorated method returns – you can prevent the signal from being sent by raising an exception from the decorated method (for instance, if the parameters are inappropriate). The signal will only actually be sent when the event loop next runs.

Example

examples/example-signal-emitter.py emits some signals on demand when one of its methods is called. (In reality, you'd emit a signal when some sort of internal state changed, which may or may not be triggered by a D-Bus method call.)

當發送訊號的方法之一被調用, examples/example-signal-emitter.py 會按要求發送一些訊號。

License for this document

Copyright 2006-2007 Collabora Ltd.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.