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

Posted

技术标签:

【中文标题】dbus-python 如何获得原生类型的响应?【英文标题】:dbus-python how to get response with native types? 【发布时间】:2012-07-14 05:54:27 【问题描述】:

我正在使用 dbus-python,我需要将响应(f.e dbus.Dictionary - 但通常是任何响应)作为本机 Python 类型。是的,可以编写递归转换器,但我想我一定遗漏了一些明显的东西?必须有一种方法可以使用 dbus 将这些怪物转换回 Python 原生类型。还是不是?

dbus.Dictionary(dbus.String(u'CanGoNext'): dbus.Boolean(True, variant_level=1), dbus.String(u'CanPause'): dbus.String(u'MinimumRate'): dbus.Int32(14, variant_level=1) ...

【问题讨论】:

【参考方案1】:

虽然 Martin 是对的,但它不适用于由 python 转换为 int 的布尔值(因为 bool cannot be subclassed)。

In [3]: print(dbus.Boolean(False))
0

不幸的是,递归转换器是保留布尔值的唯一方法。

这是一个示例实现:

import dbus


def python_to_dbus(data):
    '''
        convert python data types to dbus data types
    '''
    if isinstance(data, str):
        data = dbus.String(data)
    elif isinstance(data, bool):
        # python bools are also ints, order is important !
        data = dbus.Boolean(data)
    elif isinstance(data, int):
        data = dbus.Int64(data)
    elif isinstance(data, float):
        data = dbus.Double(data)
    elif isinstance(data, list):
        data = dbus.Array([python_to_dbus(value) for value in data], signature='v')
    elif isinstance(data, dict):
        data = dbus.Dictionary(data, signature='sv')
        for key in data.keys():
            data[key] = python_to_dbus(data[key])
    return data


def dbus_to_python(data):
    '''
        convert dbus data types to python native data types
    '''
    if isinstance(data, dbus.String):
        data = str(data)
    elif isinstance(data, dbus.Boolean):
        data = bool(data)
    elif isinstance(data, dbus.Int64):
        data = int(data)
    elif isinstance(data, dbus.Double):
        data = float(data)
    elif isinstance(data, dbus.Array):
        data = [dbus_to_python(value) for value in data]
    elif isinstance(data, dbus.Dictionary):
        new_data = dict()
        for key in data.keys():
            new_data[key] = dbus_to_python(data[key])
        data = new_data
    return data

为了在处理源自 dbus 的数据的类中更容易使用,您可以使用装饰器:

def convert_to_python(func):
    def wrapper(*args, **kwargs):
        return dbus_to_python(func(*args, **kwargs))
    return wrapper
...

@convert_to_python
def dbus_method_call(self):
    return self.dbus_proxy.Method()

这样,上面 dbus_method_call 返回的任何数据都将转换为原生 python。

查看相关问题:dbus Variant: How to preserve boolean datatype in Python?

【讨论】:

【参考方案2】:

你不需要。它们是本机类型的子类,因此您只需像使用本机类型一样使用它们:

>>> import dbus
>>> v = dbus.Dictionary(dbus.String(u'CanGoNext'): dbus.Boolean(True, variant_level=1), dbus.String(u'CanPause'): dbus.Boolean(False, variant_level=1), dbus.String(u'MinimumRate'): dbus.Int32(14, variant_level=1))
>>> print v['MinimumRate']
14
>>> if v['CanGoNext']: print 'Go'
... 
Go
>>> if v['CanPause']: print 'Pause'
... 
>>> 

【讨论】:

【参考方案3】:

在您的代码中,您无需像@Martin Vidner 所说的那样使用它们。

为了漂亮的打印,您可以使用现有的“递归转换器”,例如json

import json
print(json.dumps(d, indent=2))

输出


  "MinimumRate": 14, 
  "CanGoNext": 1, 
  "CanPause": 0

它丢失了关于类型的信息。

【讨论】:

这正是我需要做的(而且我做到了)。 JSON 臃肿,所有子类都表示为“dbus.String”等。

以上是关于dbus-python 如何获得原生类型的响应?的主要内容,如果未能解决你的问题,请参考以下文章

DBus-Python 网络管理器脚本 - WpaFlags 问题

Bluez BLE 连接监控使用 DBUS-Python

推荐使用 pydbus 或 dbus-python 有啥区别?

适用于 Windows 的 Dbus-Python

如何给出原生的复选框?

在线程内调用 dbus-python