Mining Bits and Knowledge
Python and UDisks – Part 1
14/03/11
| Este post também está disponível em Português |
Recently I received some requests asking is USBManager will someday support DeviceKit/UDev, since HAL is officially deprecated. After some researches I retook this application development.
During the research I found out some mismatching informations and a lack of examples, so I decided to post some informations about Python development with DeviceKit/UDev and DBus. I’ll cover essentially the USB storage devices issue.
Some months ago, I made a research about Python and DeviceKit and I ran into this blog post: Accessing DeviceKit with DBus and Python. I made some tests and the code worked properly. Then I wrote some more lines and leaved there for some months. Later, after a long time (and a distribution update) I retook the code to work on USBManager and noticed that it doesn’t work anymore:
>>> import dbus
>>>
>>> bus = dbus.SystemBus()
>>>
>>> proxy = bus.get_object("org.freedesktop.DeviceKit.Disks", "/org/freedesktop/DeviceKit/Disks")
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/usr/lib/pymodules/python2.6/dbus/bus.py", line 244, in get_object
follow_name_owner_changes=follow_name_owner_changes)
File "/usr/lib/pymodules/python2.6/dbus/proxies.py", line 241, in __init__
self._named_service = conn.activate_name_owner(bus_name)
File "/usr/lib/pymodules/python2.6/dbus/bus.py", line 183, in activate_name_owner
self.start_service_by_name(bus_name)
File "/usr/lib/pymodules/python2.6/dbus/bus.py", line 281, in start_service_by_name
'su', (bus_name, flags)))
File "/usr/lib/pymodules/python2.6/dbus/connection.py", line 620, in call_blocking
message, timeout)
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.DeviceKit.Disks was not provided by any .service files
>>>
Python and UDisks – Part 2
30/03/11
| Este post também está disponível em Português |
In the last post I’ve shown how to enumerate all storage devices connected to your PC using Python and UDisks. In this post I’ll show how to work with DeviceKit Disks interface.
Fist lets read some documentations! The UDisks documentation is divided in five sections:
- Disks interface;
- Device interface;
- Adapter interface;
- Expander interface;
- Port interface.
Python and UDisks – Part 3
25/04/11
| Este post também está disponível em Português |
In the last post from this series I’ve shown how to show some info about the UDisks daemon, now lets search for devices.
This first method that we’ll see is the EnumeraDevices
>>> import dbus
>>>
>>> bus = dbus.SystemBus()
>>> proxy = bus.get_object("org.freedesktop.UDisks", "/org/freedesktop/UDisks")
>>> iface = dbus.Interface(proxy, "org.freedesktop.UDisks")
>>>
>>> devs = iface.EnumerateDevices()
>>> print devs
dbus.Array([dbus.ObjectPath('/org/freedesktop/UDisks/devices/fd0'), dbus.ObjectPath('/org/freedesktop/UDisks/devices/sdb'), dbus.ObjectPath('/org/freedesktop/UDisks/devices/sr0'), dbus.ObjectPath('/org/freedesktop/UDisks/devices/sda1'), dbus.ObjectPath('/org/freedesktop/UDisks/devices/sda2'), dbus.ObjectPath('/org/freedesktop/UDisks/devices/sdc1'), dbus.ObjectPath('/org/freedesktop/UDisks/devices/sdb1'), dbus.ObjectPath('/org/freedesktop/UDisks/devices/sda'), dbus.ObjectPath('/org/freedesktop/UDisks/devices/sdb3'), dbus.ObjectPath('/org/freedesktop/UDisks/devices/sdc'), dbus.ObjectPath('/org/freedesktop/UDisks/devices/sdb2')], signature=dbus.Signature('o'))
>>> devs[0]
dbus.ObjectPath('/org/freedesktop/UDisks/devices/fd0')
>>> type(devs[0])
<type 'dbus.ObjectPath'>
>>> dir(devs[0])
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
>>>
Python and UDisks – Parte 4
23/05/11
| Este post também está disponível em Português |
We’ve seen how to connect to DBus and UDisks, then how to check some UDisks daemon settings and informations and how to query for devices. All of this isn’t so “usable” if you don’t know when a new device is connected to your PC. Of course that you could periodically poll for new devices, but this isn’t a nice solution. For a “real time” device detection, we can use signals.
There are many signals in this UDisks specifications but the most useful (in our case) are:
- The DeviceAdded Signal – Emitted when a device is added.
- The DeviceRemoved Signal – Emitted when a device is removed.
- The DeviceChanged Signal – Emitted when a device property has changed.
These descriptions were taken from UDisks Reference Manual.
Now lets see a little python snippet that shows how to work with signals.
>>> import dbus #Import necessary modules
>>> import gobject
>>> from dbus.mainloop.glib import DBusGMainLoop
>>>
>>> DBusGMainLoop(set_as_default=True) #Inform that a main loop will be used
>>>
>>> bus = dbus.SystemBus() #Start Dbus
>>> proxy = bus.get_object("org.freedesktop.UDisks", "/org/freedesktop/UDisks")
>>> iface = dbus.Interface(proxy, "org.freedesktop.UDisks")
>>>
>>> def on_device_add(dev_path):
... print 'Added',dev_path
...
>>> def on_device_changed(dev_path):
... print 'Changed',dev_path
...
>>> def on_device_removed(dev_path):
... print 'Removed',dev_path
...
>>>
>>> iface.connect_to_signal('DeviceAdded', on_device_add)
< at 9cb8b0c "type='signal',sender=':1.38',path='/org/freedesktop/UDisks',interface='org.freedesktop.UDisks',member='DeviceAdded'" on conn >
>>> iface.connect_to_signal('DeviceChanged', on_device_changed)
< at 9cb8c2c "type='signal',sender=':1.38',path='/org/freedesktop/UDisks',interface='org.freedesktop.UDisks',member='DeviceChanged'" on conn >
>>> iface.connect_to_signal('DeviceRemoved', on_device_removed)
< at 9cb8cec "type='signal',sender=':1.38',path='/org/freedesktop/UDisks',interface='org.freedesktop.UDisks',member='DeviceRemoved'" on conn >
>>>
>>> loop = gobject.MainLoop()
>>> loop.run()
Added /org/freedesktop/UDisks/devices/sdc
Added /org/freedesktop/UDisks/devices/sdc1
Changed /org/freedesktop/UDisks/devices/sdc1
Changed /org/freedesktop/UDisks/devices/sdc1
Changed /org/freedesktop/UDisks/devices/sdc
Removed /org/freedesktop/UDisks/devices/sdc1
Removed /org/freedesktop/UDisks/devices/sdc
After the loop.run() statement the program appears to be “suspended”, but it’s only watching for some signal. After that, I inserted a flash drive and it was automatically mounted. Then I unmounted it and removed. At first look (at least if you’re only looking at the static output above) this output seems to be duplicated. But it has a reason…
- The first two lines, notifies that a new “root device” (partition table) was detected (sdc), then a “new partition” (sdc1) was detected. If your flash drive has more then one partition, would be presented more notifications.
- The third output line notifies that the partition sdc1 was mounted.
- The fourth, fifth and sixth lines notifies that the device was unmounted (both partitions) and the partition “removed”.
- And the last notifies that the device was truly removed.
Now thats seems a lot more clear, doesn’t it? So, when checking for new or removed devices is interesting to filter those notifications and use only the relevant ones. This can be done querying some information about the device. I’ll show how to do this in the next post.
Python and UDisks – Part 5
05/07/11
| Este post também está disponível em Português |
Resurrecting the blog series about Python and Udisks, today I’m going to talk about how to get some more informations about the devices using properties.
About the Delay
First of all, I apologize for the delay in posting this continuation, it was harder to write than it looks. The delay is due to a change in how DBus communicate with UDisks. Since everything is very new, the documentation isn’t complete and there is no tutorial on the internet. So, my search for the error line did not return any results. Below is the code I was using and the DBus error:
>>> import dbus
>>>
>>> bus = dbus.SystemBus()
>>> proxy = bus.get_object("org.freedesktop.UDisks", "/org/freedesktop/UDisks")
>>> iface = dbus.Interface(proxy, "org.freedesktop.UDisks")
>>>
>>> devs = iface.EnumerateDevices()
>>> print devs
>>>
>>> device = devs[14]
>>> volume_obj = bus.get_object("org.freedesktop.UDisks", device)
>>> volume = dbus.Interface(volume_obj, "org.freedesktop.UDisks.Device")
>>> volume_obj.Get('','DriveConnectionInterface')
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.AccessDenied: Rejected send message, 4 matched rules; type="method_call", sender=":1.60" (uid=1000 pid=19165 comm="/usr/bin/python2 ./test-me ") interface="(unset)" member="Get" error name="(unset)" requested_reply="0" destination=":1.19" (uid=0 pid=1010 comm="/usr/lib/udisks/udisks-daemon ")
After some days of research and failed attempts I decided to do something that many people avoid: read the source code from other projects. After some research I found the liveusb-creator project, which use UDisks and DBus to detect new removable devices. My solution was in the creator.py file (more specifically at the method handle_reply, from lines 445 to 450) available here.





