Today, I've updated the gPodder website (navigation) to be more usable and easier to navigate. I've added stock Gnome icons and moved some previously top-level items into the "documentation" menu item or elsewhere. This makes navigation easier and the design also looks a bit more modern, have a look:
You can find the new gPodder website at the usual location: http://gpodder.berlios.de/. Oh, and by the way: I've just released a new version (0.9.5) today, so if you're using gPodder, be sure to check out the new release.
Sunday, August 26, 2007
Wednesday, August 22, 2007
Minimalistic Evolution phonebook extractor
If you're using Evolution as your E-Mail client and contact management application, and you like Python, here is a small snippet that allows you to dump out all phone numbers of your contacts to the console. Of course, with this code as a guide, you can produce even more useful applications ;)
What you need: Evolution, pygobject, evolution-python, Python (2.4 or higher) and some contacts in your contact list
What you need: Evolution, pygobject, evolution-python, Python (2.4 or higher) and some contacts in your contact list
#!/usr/bin/python
import evolution
import gobject
book = evolution.open_addressbook('default')
props = gobject.list_properties( evolution.EContact)
pp = [ p.name for p in props if 'phone' in p.name ]
for contact in book.get_all_contacts():
gp = contact.get_property
name = gp('file-as')
numbers = ', '.join( [ gp(p) for p in pp if gp(p) ])
if numbers:
print ': '.join( [ name, numbers ])
Thursday, August 9, 2007
Threading and Locks
This week, I've been bitten by a dead-lock bug in my website's code twice already, and I've decided to fix it, and to write about it, as it seems like a common problem when starting with threading. To use a thread lock in Python, the threading module provides a
The problem is, that if
In the Python Cookbook, there is also a decorator version of this, so when using Python 2.4 and above, and you like using decorators, try the sychronized decorator and "decorate" your function:
Threads in Python are cool, and if you're careful using them, you can make your application run faster without affecting the stability or flow of your application. A lesson I learned last weekend when a bug with locking resulting in my WSGI app dead-locking and the website unreacheable.
Lock
class that has two methods: acquire()
and release()
. Usually, one would think that thread-unsafe code should be "protected" by the lock like this ("lo" is a Lock
variable):def do_something():
lo.acquire()
do_threadunsafe_operation()
lo.release()
The problem is, that if
do_threadunsafe_operation()
raises an exception, the lock will not be released, and therefore, all subsequent calls to do_something()
will lock forever. You have to put the code in a try..finally
block to make sure the lock gets released when the function ends:def do_something():
lo.acquire()
try:
do_threadunsafe_operation()
finally:
lo.release()
In the Python Cookbook, there is also a decorator version of this, so when using Python 2.4 and above, and you like using decorators, try the sychronized decorator and "decorate" your function:
@synchronized(lo)
def do_threadunsafe_operation():
pass
Threads in Python are cool, and if you're careful using them, you can make your application run faster without affecting the stability or flow of your application. A lesson I learned last weekend when a bug with locking resulting in my WSGI app dead-locking and the website unreacheable.
Tuesday, August 7, 2007
Python Paste Easter Egg.
While looking for documentation on Paste's HTTP server module, I have found something funny:
from paste import ponyThe module documentation for paste.pony can be found here, and the corresponding highlighted source file here.
print pony.PONY.decode('base64').decode('zlib')
print pony.UNICORN.decode('base64').decode('zlib')
Sunday, August 5, 2007
Python Import Hell
Coming from a Java background to Python about two years ago, I suppose I confused Python packages and modules a bit (compare Java's packages and classes - it's a different thing!). Anyway, gPodder's current module and package structure is a bit uncoordinated, partly because I started out with the module layout early in my Python carreer and partly because I sometimes added classes where they shouldn't be placed, resulting in circular imports. I somehow managed to fix all import errors and it runs for quite a while with that layout now.
After Pierre-Luc Beaudoin informed me that his Sofa Media Center now uses gPodder as its podcast client/backend, and after looking at Pierre-Luc's code, I thought it would be good to provide some kind of gPodder API for other developers to build upon the gPodder functionality. This way, gPodder would be a modular app with a GUI, but it could also function as simple podcast client library (if needed).
So, yesterday, I started to restructure the gPodder package/module layout a bit. While doing this, I had some problems with circular imports. The problem was that I had a "gpodder" module in the "gpodder" package, and Python 2.4's "import" statement first searches the current package and then the "global" package/module path. I read about Python's built-in Package support that is available since Python 1.5. Great! But it already mentions that there could be problems with relative imports. Another article entited Importing Python Modules then explained the partly confusing import hell of Python. The article says one should "always use import X" (except for some special cases).
Circular imports can often easily be avoided by placing depended-on code in seperate modules. It's also good to see that this problem is partly solved by PEP 328, which is (optionally) available starting with python 2.5, throws a warning and 2.6 and will be the default in Python 2.7: Absolute imports. This way, naming a package-local module like a top-level package will not result in confusion. One can either use "import X" to do an absolute import or do "from . import X" to do a relative import. Currently (Python 2.4), "import X" will prefer the local module over a global package/module with the same name. Confusing, isn't it?
After Pierre-Luc Beaudoin informed me that his Sofa Media Center now uses gPodder as its podcast client/backend, and after looking at Pierre-Luc's code, I thought it would be good to provide some kind of gPodder API for other developers to build upon the gPodder functionality. This way, gPodder would be a modular app with a GUI, but it could also function as simple podcast client library (if needed).
So, yesterday, I started to restructure the gPodder package/module layout a bit. While doing this, I had some problems with circular imports. The problem was that I had a "gpodder" module in the "gpodder" package, and Python 2.4's "import" statement first searches the current package and then the "global" package/module path. I read about Python's built-in Package support that is available since Python 1.5. Great! But it already mentions that there could be problems with relative imports. Another article entited Importing Python Modules then explained the partly confusing import hell of Python. The article says one should "always use import X" (except for some special cases).
Circular imports can often easily be avoided by placing depended-on code in seperate modules. It's also good to see that this problem is partly solved by PEP 328, which is (optionally) available starting with python 2.5, throws a warning and 2.6 and will be the default in Python 2.7: Absolute imports. This way, naming a package-local module like a top-level package will not result in confusion. One can either use "import X" to do an absolute import or do "from . import X" to do a relative import. Currently (Python 2.4), "import X" will prefer the local module over a global package/module with the same name. Confusing, isn't it?
Subscribe to:
Posts (Atom)