Try-except versus if-else in Python 3.5


Today I ran again in the question why to use if-else when try-except is shorter?

There is a semantic part that we loose information on a try-except as we don’t know what the developer did expect in the most case and there is a performance part. I found a test for python 2 (Try / Except Performance in Python: A Simple Test) with simple assumptions: we try to get a value in a one keyed dictionary and make iterations to get a statistic on this access. I made it a little more complex with a dictionary with 10,001 keys.

Results analysis:

  • if-else take the same amount of time in both case
  • try-expect is 2 times faster than if-else when it no raise the exception
  • try-expect is 5 times slower when the exception is raised

Then the if-else has a predictable comportment and help the maintainer.

I’m agree that the semantic part of the if-else can be replace by a comment but i still not recommend to try-except if it is not to raise an exception.

 

The results:

The case where the key does not exist: 
 
1,000 iterations: 
with_try (0.250 ms) 
with_try_exc (0.291 ms) 
without_try (0.119 ms) 
without_try_not (0.120 ms) 
 
1,000,000 iterations: 
with_try (231.647 ms) 
with_try_exc (263.633 ms) 
without_try (119.238 ms) 
without_try_not (118.602 ms) 
 
1,000,000,000 iterations: 
with_try (224659.381 ms) 
with_try_exc (260333.897 ms) 
without_try (109796.531 ms) 
without_try_not (111871.690 ms) 
 
 
The case where the key does exist: 
 
1,000 iterations: 
exists_with_try (0.066 ms) 
exists_with_try_exc (0.070 ms) 
exists_without_try (0.166 ms) 
exists_without_try_not (0.180 ms) 
 
1,000,000 iterations: 
exists_with_try (57.661 ms) 
exists_with_try_exc (56.909 ms) 
exists_without_try (113.633 ms) 
exists_without_try_not (116.340 ms) 
 
1,000,000,000 iterations: 
exists_with_try (57650.440 ms) 
exists_with_try_exc (57395.376 ms) 
exists_without_try (114659.023 ms) 
exists_without_try_not (117646.034 ms)

 

The code:

#!/usr/bin/env python3

import time

d = dict.fromkeys(range(0, 10000), 0)
d['somekey'] = 1

ITERATIONS = (1000, 1000*1000, 1000*1000*1000)

def time_me(function):
    def wrap(*arg):
        start = time.time()
        r = function(*arg)
        end = time.time()
        print("%s (%0.3f ms)" % (function.__name__, (end-start)*1000))
        return r
    return wrap


# Not Existing
@time_me
def with_try(iterations):
    for i in range(0, iterations):
        try:
            get = d['notexist']
        except:
            pass

@time_me
def with_try_exc(iterations):
    for i in range(0, iterations):
        try:
            get = d['notexist']
        except Exception:
            pass

@time_me
def without_try(iterations):
    for i in range(0, iterations):
        if d.get('notexist'):
            pass
        else:
            pass

@time_me
def without_try_not(iterations):
    for i in range(0, iterations):
        if not d.get('notexist'):
            pass
        else:
            pass



# Existing
@time_me
def exists_with_try(iterations):
    for i in range(0, iterations):
        try:
            get = d['somekey']
        except:
            pass

@time_me
def exists_with_try_exc(iterations):
    for i in range(0, iterations):
        try:
            get = d['somekey']
        except Exception:
            pass

@time_me
def exists_without_try(iterations):
    for i in range(0, iterations):
        if d.get('somekey'):
            pass
        else:
            pass

@time_me
def exists_without_try_not(iterations):
    for i in range(0, iterations):
        if not d.get('somekey'):
            pass
        else:
            pass


print ("\n\nThe case where the key does not exist:")
for iteration in ITERATIONS:
    print ("\n%d iterations:" % iteration)
    with_try(iteration)
    with_try_exc(iteration)
    without_try(iteration)
    without_try_not(iteration)


print ("\n\nThe case where the key does exist:")
for iteration in ITERATIONS:
    print ("\n%d iterations:" % iteration)
    exists_with_try(iteration)
    exists_with_try_exc(iteration)
    exists_without_try(iteration)
    exists_without_try_not(iteration)

Le livre Culture Libre de Lawrence Lessig disponible en français


Le fameux livre « Culture Libre » est enfin disponible en français sur lulu.com. Je ne vais pas paraphraser l’auteur ou la foultitude de blogueur qui en parle. C’est l’un de mes livres de chevets, un incontournable pour comprendre le mouvement du libre dans son ensemble et parfois aussi comment notre société s’est construite et vers quoi elle tend.

Pour ceux qui supporte l’anglais, allez faire un tour sur http://free-culture.cc/ pour comprendre la génèse du livre.

Toute mes pensées vont vers notre camarade Yves qui aurait tant aimé le partager avec nous et avec le public des JDLL et qui nous a quitté.

 

 

When UnicodeDecodeError become irrational check $LANG


I spent hours this week trying to understand how an installation script can fail on some installations.

In input we have an utf-8 encoded file and we add some xml files, also ‘utf-8’ encoded. These are parsed with Markdown.

python -m lom2mlr.markdown -l -c rationale.md

It is really simple but sometimes we ran into a strange error:

Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
"__main__", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/home/edegoute/Projects/lom2mlr/lom2mlr/lom2mlr/markdown/__main__.py", line 3, in <module>
compile()
File "lom2mlr/markdown/__init__.py", line 55, in compile
extensions=extensions)
File "/home/edegoute/Projects/lom2mlr/local/lib/python2.7/site-packages/markdown/__init__.py", line 529, in markdownFromFile
kwargs.get('encoding', None))
File "/home/edegoute/Projects/lom2mlr/local/lib/python2.7/site-packages/markdown/__init__.py", line 441, in convertFile
html = self.convert(text)
File "/home/edegoute/Projects/lom2mlr/local/lib/python2.7/site-packages/markdown/__init__.py", line 375, in convert
newRoot = treeprocessor.run(root)
File "lom2mlr/markdown/test_mlr.py", line 76, in run
print(" " * int(element.tag[1]) + element.text)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xc9' in position 4: ordinal not in range(128)

First, it was difficult to understand how an unicode error can raise an iso-8859-1 problem on utf-8 files. Going deep I found some known problems with ‘codecs.open’ in python2.7 but no solution. I tried to force Markown to treat these files as ‘iso-8859-1’ files, then it ran an utf-8 unicode error at the same line not in the opening. It was sounding too many magic for me.

At that point, I checked again the installation was identical: same python version, same pip version, same eggs versions. I tried some egg upgrade without any success. And finally came the idea to check environment variables. Bingo! On all systems with failing installations we have no localization ($LANG=C). The fix was so simple:

export LANG=en_US.UTF-8

That’s it!

I still don’t understand the magic in the codecs python module. Why it computes a different encoding when the function call already asks for one? The workaround is simple for programmers.

La culture libre, la vie publique et le droit à l’oubli


Le logiciel libre et la culture libre se forment à partir d’un principe fondateur : le partage. Derrière ce partage, il y a plusieurs buts : aider l’apprentissage, faciliter la reproductibilité, améliorer l’existant, et publier son expérience. Dit autrement :  transmettre, reproduire, étudier, distribuer.

Publier une informations dans un média, c’est sortir un élément de vie privée pour l’exposer au public. C’est le partage d’une expérience privée au grand jour, même si ce n’est pas la nôtre. Pour un journaliste, c’est rarement son expérience qui est partagée : il sert d’intermédiaire pour la révéler avec ou sans parti pris.

Le droit à l’oubli, c’est casser ce partage en mettant en avant la seule vie privée dans la balance. Plus moyen de transmettre cette information qui ne devrait exister, de distribuer ce que l’on a pu apprendre. Dans certains cas il serait possible d’arguer de la conception chrétienne du pardon : le temps a passé et les fautes ont été payées à la société… ou pas. La plupart du temps, ce qui est recherche c’est masquer les faits, l’oblivion. Comme dans ce passé proche, ou ce futur proche, dans lequel les autodafés détruisaient les livres qui ne relevaient pas de la morale d’une religion ou de la ligne d’un parti.

Ce qui est devenu public fait partie de l’inconscient collectif. En retirer une partie  ampute cet inconscient d’un souvenir. Sans nous en rendre bien compte, petit à petit, nous effaçons nos traces. Nous sélectionnons nos expériences pour nous façonner un futur. Mais qu’advient-il d’un bâtiment dont on prend les matériaux des étages inférieurs pour construire le sommet : il s’effondre. Effacer le passé, c’est aussi perdre nos racines, refuser notre apprentissage, nos doutes. Quelles seront nos valeurs refuges ? L’égocentrisme, le communautarisme et toutes les formes de repli sur soi qui nous ferons revenir aux pratiques des siècles passés.

Comment défendre la culture libre, le partage, et le droit à l’oubli ? Ce paradoxe vient du militantisme associé à la diffusion des idées de la culture libre. Nager à contre courant nécessite parfois d’avancer masqué. Entre théorie du complot et menace bien existante certains aimeraient faire table rase pour se protéger en oubliant qu’être militant c’est avant tout un don de soi, parfois corps et âme.

Puis vient le temps où il est temps de passer la main et de se retirer de la vie publique. L’envie de faire table rase et de redémarrer à zéro est tenace. Cependant, lorsque l’on a défendu le partage, il est compliqué de renier ses valeurs en imposant aux autres l’oubli. Pour un militant en activité, c’est juste inconcevable de défendre les deux à la fois : c’est comme vouloir à la fois la lumière et les ténèbres en oubliant les 50 nuances de gris, comme refuser de partager avec ceux qui ne partagent pas.

Beats audio setup for HP Envy on recent Ubuntu


But the package hda-jack-retask is stuck in raring. The goal here is to allow you to install the package in your brand new Ubuntu. Replace « utopic » each time it is mentionned velow by your version.


sudo apt-add-repository -s ppa:diwic/hda
sudo apt-get update

Then edit  the file « /etc/apt/sources.list.d/diwic-ubuntu-hda-utopic.list » to replace utopic by saucy.


cd Downloads
mkdir hda-jack-retask
sudo apt-get build-dep hda-jack-retask
apt-get source hda-jack-retask
cd hda-jack-retask-0.20130613+raring

Now, you have to edit the debian/control file to sign the archive with you gpg key.
All spaces are important.

hda-jack-retask (0.20130613+utopic) utopic; urgency=low

* No-change upload for utopic

— Encolpe Degoute <encolpe.degoute@free.fr> Fri, 16 Jan 2015 11:00:00 +0200

Now, prepare your local package ans install it :


dpkg-buildpackage -rfakeroot
sudo dpkg -i ../hda-jack-retask_0.20130613+utopic_amd64.deb

Remove the PPA:

sudo apt-add-repository -r ppa:diwic/hda

The overall process should take less than 10 minutes.

Interdit aux moins de 16 ans


Linda's Blog

Séquence interdite aux moins de 16 ans..

Il a même obtenu un prix au Piff, le festival du cinéma fantastique, le film Alelluia de Fabrice du Welz.

Du Welz qui, avec ce dernier film, est revenu à ses fondamentaux, à ce qu’il le faisait triper quand il était ado. A savoir l’hémoglobine, et à ce Massacre à la tronçonneuse, le film de Tobe Hooper qui lui donna à 16 ans, l’envie viscérale de faire du cinéma.

Donc avec Alleluia, son nouveau film, on peut dire qu’on est servi côté bain de sang. Au pluriel, les bains de sang.

Une violence visuelle qui cela dit n’est pas gratuite mais qui se met au service de la psychose de ses personnages. En l’occurrence, un manipulateur de femmes délaissées, qu’il séduit pour leur soutirer de l’argent, et une des proies qui va s’avérer peut-être bien plus féroce que lui. Car une histoire passionnelle…

View original post 185 mots de plus

De Maidan au Donbass


Linda's Blog

Lyon a en partie les yeux tournés vers l’Ukraine.

La situation en Ukraine, c’est le collectif Item qui en parle. L’atelier item, c’est un lieu à Lyon, dédié à l’image documentaire. Un espace qu’un collectif indépendant d’une petite dizaine de photographes et vidéastes, historiquement lyonnais a ouvert il y a 4 ans.

Cet espace fonctionne main dans la main avec Visa pour l’image et a donc décidé de mettre en avant celui qui avait eu cette année le Visa d’or : Guillaume Herbault.

Guillaume Herbault, on l’avait reçu dans la matinale il y a deux ans, c’est une pointure dans la photo documentaire. Il avait déjà eu un world press photo. En 1995, il a fondé, avec d’autres photographes, l’agence “L’oeil public”. Et il va en Ukraine tous les ans depuis 2001, depuis un reportage sur Tchernobyl où il s’est pris d’amour pour le pays. Il a suivi la révolution…

View original post 125 mots de plus

Recent work with RelStorage


Chatterbox, Reloaded

The KARL project has been focused in the last year on some performance and scalability issues. It’s a reasonably big database, ZODB-atop-RelStorage-atop-PostgreSQL. It’s also heavily security-centric with decent writes, so CDNs and other page caching wasn’t going to help.

I personally re-learned the ZODB lesson that the objects needed for your view better be in memory. Our hoster is 32-bit-only, so that made us learn a little more and think about the tradeoffs. Adding more threads means higher memory usage per process. We get some concurrency as PG requests release the GIL, but that’s hard to bank on. Instead you have a bunch of single-connection processes, but then you get little cache affinity. One bad view leads to 20k objects getting requested. The user hits reload a few times, and your site is hung until PG is finished.

We use memcache as well, but that is also limited to 2…

View original post 346 mots de plus

Installation de Movim


Movim est l’un des projets plus si récents que ça voulant faire émerger les réseaux sociaux décentralisés. Sa particularité est d’utiliser un protocole ouvert, XMPP, pour l’échange de données.
Dans le cadre de l’initiation aux logiciels libres au sein de la Licence Pro Colibre, j’ai voulu, naïvement, installer Movim pour faire goûter aux étudiants une nouvelle sensation de liberté. C’est un peu trop complexe de prime abord. Nous allons nous limiter à installer movim seul.

Récupération de l’archive

Tout d’abord, il faut récupérer l’archive et l’installer à un endroit utilisable par apache2 :
wget https://launchpad.net/movim/0.8/0.8.1/+download/movim-0.8.1.zip
Vérifions l’intégrité de l’archive avec md5 :
wget https://launchpad.net/movim/0.8/0.8.1/+download/movim-0.8.1.zip/+md5
md5sum -c +md5
#movim-0.8.1.zip: Réussi
Vérifions l’auteur de l’archive avec gnupg :
wget https://launchpad.net/movim/0.8/0.8.1/+download/movim-0.8.1.zip.asc
gpg --verify movim-0.8.1.zip.asc
# gpg: Signature faite le mar. 05 août 2014 00:08:11 CEST avec la clef RSA d'identifiant 1D3810D9
# gpg: Impossible de vérifier la signature : clef publique introuvable
gpg --search-keys 1D3810D9
gpg --verify movim-0.8.1.zip.asc
C’est bien Timothée Jaussoin qui a signé l’archive.

Installation de Movim

cd Téléchargements
mv ../movim-8.0.1.zip .
unzip movim-0.8.1.zip
sudo cp -r movim-0.8.1 /var/www/html/movim
sudo chown -R www-data:www-data /var/www/html/movim
sudo -H -s -u www-data
cd /var/www/html/movim
mv config/db.example.inc.php config/db.inc.php
editor config/db.inc.php
exit
Il faut maintenant éditer le fichier config/db.inc.php pour mettre les informations de connexion à la base MySQL.
Si vous n’avez pas encore créé votre base de données il faut le faire à la main avec un outil du type MySQL Workbench. N’oubliez pas de créer un utilisateur spécifique.
sudo apt-get install mysql-workbench mysql-server
Dans la foulée, installons les dépendances de movim :
sudo apt-get install php5 php5-curl php5-gd php5-mysql mysql-common mysql-client

Configuration de FPM et d’Apache2

Récupération des dépendances de PHP FPM :
sudo apt-get install libapache2-mod-fastcgi apache2-mpm-event apache2 php5-fpm
sudo a2enmod actions fastcgi alias
sudo service apache2 restart
Créer un fichier /etc/apache2/conf-available/php5-fpm.conf contenant la configuration ci-dessous :
<IfModule mod_fastcgi.c>
        AddHandler php5-fcgi .php
        Action php5-fcgi /php5-fcgi
        Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi
        FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -socket /var/run/php5-fpm.sock -idle-timeout 300 -pass-header Authorization
        <Directory /usr/lib/cgi-bin>
                Options ExecCGI FollowSymLinks
                SetHandler fastcgi-script
                Require all granted
        </Directory>
</IfModule>
Pour l’activer il faut passer par a2enconf
sudo a2enconf php5-fpm
sudo service apache2 restart

Configuration à rajouter à la fin du fichier /etc/php5/fpm/php-fpm.conf

[movim]
user = www-data
group = www-data
listen = 127.0.0.1:9001
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
 
pm = ondemand
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

request_terminate_timeout = 300
 
php_admin_value[open_basedir] = none
Puis redémarrer le service
sudo service php5-fpm restart

Configuration de Movim

Normalement, tout est intsallé. Il reste à configurer dans l’interface web :

http://localhost/movim/?q=admin

  • Passez le site en Français et avec la zone horaire de Pais.
  • Choisissez movim.eu comme serveur Bosh : http://movim.eu:5290/http-bind
  • Dans l’onglet des paramètres de la base de données, lancez la création des tables
  • Vérifiez votre configuration dans l’onglet suivant
Maintenant, il nous faut créer notre compte chez movim.eu en passant par notre nouvelle page d’accueil :

http://localhost/movim

Conclusion

Pas mal de petites choses n’étaient pas évidente dans la documentation actuelle. Par exemple un script de création de la base de données et d’un utilisateur associé facilitera la vie d’un installateur débutant (d’où l’utilisation de Workbench).
La prochaine étape est d’installer un serveur BOSH compatible avec toutes les fonctionnalités de Movim. Sûrement Metronome IM.
Update : Rajout de la gestion du timeout

Créer une carte vectorielle d’un lieu à partir d’OpenStreetMap


Depuis trois ans maintenant j’aide à organiser un événement en extérieur à Lyon. Notre problème récurrent est d’avoir des plans de bonnes qualités et de pouvoir les échanger dans des formats utilisables par tout le monde.  Nous avions utilisé OpenStreetMap pour créer un premier plan au format PNG il y a plusieurs années. Malheureusement, avec le temps et les multiples surcouches ce fichier était de plus en plus dégradé. Pas moyen de mettre la main sur un quelconque fichier vectoriel pour repartir sur un fichier propre.

Exporter des données depuis le site OpenStreetMap est plutôt simple :

http://www.openstreetmap.org/export#map=17/45.75817/4.84242

Dans mon cas j’ai sélectionné une zone comprise entre le pont Wilson et le pont de la Guillotière à Lyon. Vous obtenez un fichier map.osm près à l’emploi.

Restant que le format OSM n’est pas utilisable directement pour autre chose que de l’édition du plan. J’aimerai passer au format SVG qui est utilisable par Inkscape. Une rubrique est dédiée à ce sujet sur le site : Ways to create an SVG map from OpenStreetMap. Mais elle n’est pas à jour. Les méthodes décrites sont au mieux trop complexes, et pire plus valable.

Les méthodes les plus simples étaient liées au logiciel OSMARender qui n’est plus maintenu depuis un an. Là encore ce n’était pas très clair et il m’a fallu tâtonner un moment pour arriver à ce résultat :

svn co http://svn.openstreetmap.org/applications/rendering/osmarender
cd osmarender
cp ~/Downloads/map.osm stylesheets/data.osm
xsltproc -o ~/desktop/map.svg xslt/osmarender.xsl ./stylesheets/osm-map-features-z17.xml

Plan_vide_OSM

À partir de ce fichier map.svg vous pouvez travailler avec Inkscape pour nettoyer les précisions excédentaires et rajouter vos informations. Après quelques de travail cela permet d’avoir une version assez épurée.

WordPress n’acceptant pas les fichiers SVG je montre le résultat en PNG.

Suivre

Recevez les nouvelles publications par mail.

Rejoignez 361 autres abonnés