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)

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 應用程序能夠輸出對象讓其它應用使用。爲了能夠使用另一個應用程序提供的對象,你需要知道:

  • The bus name. This identifies which application you want to communicate with. You'll usually identify applications by a well-known name, which is a dot-separated string starting with a reversed domain name, such as org.freedesktop.NetworkManager or com.example.WordProcessor.

    bus名稱(bus name)。它標識着你想與哪個應用程序進行通訊。你會常常通過衆所周知的名稱(well-known name)來標識一個應用程序,它是反轉域名後用 `.' 分割的字符串,例如: org.freedesktop.NetworkManager 或 com.example.WordProcessor。

  • The object path. Applications can export many object - for instance, example.com's word processor might provide an object representing the word processor application itself and an object for each document window opened, or it might also provide an object for each paragraph within a document.

    對象路徑(object path)。應用程序可以輸出很多對象,例如, example.com 的文字處理進程會提供一個代表文字處理進程自身對象,還會爲每一個打開的文檔窗口都提供一個對象。或者它還可以爲一個文檔的每一段都提供一個對象。

    To identify which one you want to interact with, you use an object path, a slash-separated string resembling a filename. For instance, example.com's word processor might provide an object at / representing the word processor itself, and objects at /documents /123 and /documents/345 representing opened document windows.

    爲了標識你想與誰通訊,你需要使用對象路徑(object path),它是一個用 `/' 分割的字符串,就像文件名一樣。例如, example.com 的文字處理進程會提供一個對像 `/' ,它代表文字進程自身, 和代其它已打開文檔窗口的對象,/documents/123 和 /document/345 。

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 將接受:

  • for Boolean parameters, any object (converted as if via int(bool(...)))

    對於 Boolean 參數,任何 object (被轉換通過 int(bool(...)))

  • for byte parameters, a single-character string (converted as if via ord())

    對於 byte 參數,一個單字符串 (single-character string) (被轉換通過 ord())

  • for byte and integer parameters, any integer (must be in the correct range)

    對於 byte 和 integer 參數,任何 integer (必須在正確的範圍內)

  • for object-path and signature parameters, any str or unicode subclass (the value must follow the appropriate syntax)

    對於 object-path 和 signature 參數,任何 str 或 unicode subclass (必須有適當的語義)

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。一段時間後,當事件循環執行時,它們中的一個將會發生:

  • the reply_handler will be called with the method's return values as arguments; or

    reply_handler 將會被調用,它的參數是上面方法的返回值。

  • the error_handler will be called with one argument, an instance of DBusException representing a remote exception.

    error_handler 將被調用,它的參數是一個代表遠程異常的 DBusException 的一個實例。

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 方法。當一個匹配的信號收到後,安排好的回調函數將被調用,傳入以後參數:

  • a callable (the handler_function) which will be called by the event loop when the signal is received - its parameters will be the arguments of the signal

    當收到信號時,一個可調函數 (callable) (the handler_fucntion) 將會被事件循環調用 - 它的參數是信息的參數。

  • the signal name, signal_name: here None (the default) matches all names

    信號名稱,signal_name: 這裏爲 None (默認) 則匹配所有名稱。

  • the D-Bus interface, dbus_interface: again None is the default, and matches all interfaces

    D-Bus 接口, dbus_interface: None 是默認的,匹配所有接口。

  • a sender bus name (well-known or unique), bus_name: None is again the default, and matches all senders. Well-known names match signals from whatever application is currently the primary owner of that well-known name.

    發送者的 bus 名稱 (well-known 或 unique),bus_name: None是默認的,匹配所有發送者。Well-known 名稱匹配來自當前擁有那個 well-known 名稱的應用程序的信號,無論應用程序是誰。

  • a sender object path, path: once again None is the default and matches all object paths

    一個發送者的 object path,path: None 是默認的,匹配所有 object paths,

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 將安排一個回調函數被調用。

  • the name of the signal

    信號名稱

  • a callable (the handler function) which will be called by the event loop when the signal is received - its parameters will be the arguments of the signal

    當收到信號時,一個可調函數 (callable) (the handler_fucntion) 將會被事件循環調用 - 它的參數是信息的參數。

  • the handler function, a callable: the same as for add_signal_receiver

    處理函數 (callable): 與 add_signal_receiver 相同

  • the keyword argument dbus_interface qualifies the name with its interface

    關鍵詞參數 dbus_interface 限定接口的名稱。

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.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章