Mining Bits and Knowledge
USBManager
Python e UDisks – Parte 5
05/07/11
| This post is also available in English |
Ressuscitando a série de artigos sobre Python e Udisks hoje vou mostrar como obter mais informações dos dispositivos através das propriedades.
Sobre o Atraso
Antes de tudo, peço desculpas pela demora em postar essa continuação, ela foi mais difícil de escrever do que parece. Essa demora se deve à mudança da forma como o DBus se comunica com o UDisks. Como tudo ainda é muito novo e não há um documentação completa e tão pouco tutoriais na internet, minhas buscas pela linha de erro não retornavam nenhum resultado. Abaixo está o código que eu estava utilizando e o erro que o DBus me apresentava:
>>> 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 ")
Após dias de pesquisas e tentativas frustradas resolvi fazer algo que muitos evitam: ler código fonte de outros projetos. Depois de algumas pesquisas acabei encontrando o projeto liveusb-creator que utiliza o UDisks e o DBus para detectar dispositivos removíveis. Minha solução estava no arquivo creator.py (mais especificamente no método handle_reply, linhas 445 a 450) disponível aqui.
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.
Python e UDisks – Parte 4
23/05/11
| This post is also available in English |
Nos já vimos, como conectar ao DBus e o UDisks, em seguida vimos como verificar algumas configurações e informações do daemon do UDisks e também como buscar por dispositivos conectados. Tudo isso não é muito “usável” se você não souber quando uma novo dispositivo foi conectado ao seu computador. Claro que você pode ficar testando periodicamente se algum dispositivo foi adicionado, mas esta não é uma solução muito elegante. Para uma detecção de dispositivos “em tempo real” nos utilizamos sinais.
Existem diversos sinais especificados no Udisks, mas os mais úteis (para o nosso caso) são:
- O sinal DeviceAdded – Emitido sempre que um dispositivo é adicionado.
- O sinal DeviceRemoved – Emitido quando um dispositivo é removido.
- O sinal DeviceChanged – Emitido sempre que a propriedade de um dispositivo é alterada.
Essas descrições foram tiradas do Manual de Referência do UDisks.
Mas antes de seguirmos adiante, o que são sinais? Sinais são chamadas assíncronas, de uma forma simples podemos dizer que são “eventos”. Com a utilização de chamadas assíncronas nosso programa pode realizar operações e processamentos e ser “interrompido” quando um evento ocorrer. Vinculado a esse evento está uma função de tratamento (handler).
Agora vamos ver um trecho de código Python que mostra como lidar com esses sinais.
>>> import dbus #Importa módulos necessários
>>> import gobject
>>> from dbus.mainloop.glib import DBusGMainLoop
>>>
>>> DBusGMainLoop(set_as_default=True) #Informa a utilização de um main loop
>>>
>>> bus = dbus.SystemBus() #Inicia o DBus
>>> proxy = bus.get_object("org.freedesktop.UDisks", "/org/freedesktop/UDisks")
>>> iface = dbus.Interface(proxy, "org.freedesktop.UDisks")
>>>
>>> def on_device_add(dev_path):
... '''Handler para o evento DeviceAdded'''
... print 'Adicionado:',dev_path
...
>>> def on_device_changed(dev_path):
... '''Handler para o evento DeviceChanged'''
... print 'Modificado:',dev_path
...
>>> def on_device_removed(dev_path):
... '''Handler para o evento DeviceRemoved'''
... print 'Removido:',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() #loop infinito
Adicionado: /org/freedesktop/UDisks/devices/sdc
Adicionado: /org/freedesktop/UDisks/devices/sdc1
Modificado: /org/freedesktop/UDisks/devices/sdc1
Modificado: /org/freedesktop/UDisks/devices/sdc1
Modificado: /org/freedesktop/UDisks/devices/sdc
Removido: /org/freedesktop/UDisks/devices/sdc1
Removido: /org/freedesktop/UDisks/devices/sdc
As linhas 24, 26 e 28 são responsáveis por conectar o “evento” do sinal à função de tratamento do evento (event handler).
Após a linha loop.run(), o programa parece que está “suspenso”, mas está apenas aguardando a ocorrência de algum sinal. Após isso, eu inseri uma pen drive, e ela foi montada automaticamente. Em seguida eu a desmontei e a removi. Olhando rapidamente (pelo menos se você estiver olhando a saída estática acima) temos a impressão de que estão sendo geradas outputs duplicadas. Mas isso tem uma boa explicação…
- As primeiras duas linhas notificam que um novo “root device” (tabela de partição) foi detectado (sdc), em seguida a “nova partição” (sdc1) foi detectada. Se sua pendrive tivesse mais partições teríamos mais outputs.
- A terceira linha notifica que a partição sdc1 foi montada.
- A quarta, quinta e sexta linha notifica que o dispositivo foi desmontado (ambas as partições) e a partição “removida”.
- E a última linha notifica que o dispositivo foi realmente removido.
Agora tudo parece mais claro, não? Então, quando buscamos por novos dispositivos é interessante filtrar essas notificações e manter somente as que são relevantes. Isso será feito buscando informações sobre o dispositivo. Eu irei mostrar como fazer isso no próximo post, até lá…
... '''Handler para o evendo DeviceAdded'''
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 e UDisks – Parte 3
25/04/11
| This post is also available in English |
No último post desta série eu mostrei como obter algumas informações úteis sobre o daemon UDisks, agora vamos ver como buscar dispositivos com ele.
O primeiro método que iremos ver é o EnumerateDevices:
>>> 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 – 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 e UDisks – Parte 2
30/03/11
| This post is also available in English |
Há alguns posts eu mostrei como listar todos os dispositivos de armazenamento conectados ao seu PC usando Python e UDisks. Neste post irei mostrar como trabalhar com a interface Disks do DeviceKit.
Primeiramente vamor ler algumas documentações! A documentação do UDisks é dividida em cinco sessões:
- Interface Disks;
- Interface Device;
- Interface Adapter;
- Interface Expander;
- Interface Port.
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 e UDisks – Parte 1
14/03/11
| This post is also available in English |
Recentemente recebi diversos contatos de pessoas querendo saber se o USBManager iria suportar ou não o DeviceKit/UDev, uma vez que o HAL foi oficialmente descontinuado, então acabei retomando o desenvolvimento desse aplicativo.
Acabei percebendo algumas diferenças e pouca referência na internet, por isso vou postar algumas informações a respeito do desenvolvimento usando o DBus e o DeviceKit para trabalhar com dispositivos de armazenamento via USB.
Há algum tempo, fiz uma pesquisa sobre Python e o DeviceKit e encontrei esse post: Accessing DeviceKit with DBus and Python. Eu havia feito alguns testes e o código funcionou perfeitamente. Escrevi algumas linhas a mais e guardei para mexer em um outro dia. Depois de muito tempo (e uma atualização de distribuição) resolvi mexer novamente no USBManager e percebi que o trecho de código não funciona mais:
>>> 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 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
>>>





