FAQ sur la bibliothèque et les extension

Sommaire

Questions générales sur la bibliothèque

Comment puis-je trouver un module ou une application pour exécuter la tâche X?

Regardez si la bibliothèque standard contient un module approprié (avec l’expérience, vous connaitrez le contenu de la bibliothèque standard et pourrez sauter cette étape).

For third-party packages, search the Python Package Index or try Google or another Web search engine. Searching for « Python » plus a keyword or two for your topic of interest will usually find something helpful.

Où se situe le fichier source math.py (socket.py, regex.py, etc.) ?

Si vous ne parvenez pas à trouver le fichier source d’un module, c’est peut-être parce que celui-ci est un module natif ou bien un module implémenté en C, C++, ou autre langage compilé, qui est chargé dynamiquement. Dans ce cas, vous ne possédez peut-être pas le fichier source ou celui-ci est en réalité stocké quelque part dans un dossier de fichiers source C (qui ne sera pas dans le chemin Python), comme par exemple mathmodule.c.

Il y a (au moins) trois types de modules dans Python

  1. modules écrits en Python (.py) ;

  2. modules écrits en C et chargés dynamiquement (.dll, .pyd, .so, .sl, .etc) ;

  3. les modules écrits en C et liés à l’interpréteur ; pour obtenir leur liste, entrez :

    import sys
    print sys.builtin_module_names
    

Comment rendre un script Python exécutable sous Unix ?

Deux conditions doivent être remplies : les droits d’accès au fichier doivent permettre son exécution et la première ligne du script doit commencer par #! suivi du chemin vers l’interpréteur Python.

La première condition est remplie en exécutant chmod +x scriptfile ou chmod 755 scriptfile.

Il y a plusieurs façons de remplir la seconde. La plus simple consiste à écrire au tout début du fichier

#!/usr/local/bin/python

en utilisant le chemin de l’interpréteur Python sur votre machine.

Pour rendre ce script indépendant de la localisation de l’interpréteur Python, il faut utiliser le programme env. La ligne ci-dessous fonctionne sur la quasi-totalité des dérivés de Unix, à condition que l’interpréteur Python soit dans un dossier référencé dans la variable PATH de l’utilisateur :

#!/usr/bin/env python

Ne faites pas ceci pour des scripts CGI. La variable PATH des scripts CGI est souvent très succincte, il faut par conséquent préciser le chemin absolu réel de l’interpréteur.

Occasionally, a user’s environment is so full that the /usr/bin/env program fails; or there’s no env program at all. In that case, you can try the following hack (due to Alex Rezinsky):

#! /bin/sh
""":"
exec python $0 ${1+"$@"}
"""

Le léger inconvénient est que cela définit la variable __doc__ du script. Cependant, il est possible de corriger cela en ajoutant

__doc__ = """...Whatever..."""

Existe-t’il un module curse ou termcap en Python ?

For Unix variants the standard Python source distribution comes with a curses module in the Modules subdirectory, though it’s not compiled by default. (Note that this is not available in the Windows distribution – there is no curses module for Windows.)

Le module curses comprend les fonctionnalités de base de curses et beaucoup de fonctionnalités supplémentaires provenant de ncurses et de SYSV curses comme la couleur, la gestion des ensembles de caractères alternatifs, la prise en charge du pavé tactile et de la souris. Cela implique que le module n’est pas compatible avec des systèmes d’exploitation qui n’ont que le curses de BSD mais, de nos jours, de tels systèmes d’exploitation ne semblent plus exister ou être maintenus.

Pour Windows : utilisez le module consolelib.

Existe-t’il un équivalent à la fonction C onexit() en Python ?

Le module atexit fournit une fonction d’enregistrement similaire à la fonction C onexit().

Pourquoi mes gestionnaires de signaux ne fonctionnent-t’ils pas ?

Le problème le plus courant est d’appeler le gestionnaire de signaux avec les mauvais arguments. Un gestionnaire est appelé de la façon suivante

handler(signum, frame)

donc il doit être déclaré avec deux paramètres :

def handler(signum, frame):
    ...

Tâches fréquentes

Comment tester un programme ou un composant Python ?

Python fournit deux cadriciels de test. Le module doctest cherche des exemples dans les docstrings d’un module et les exécute. Il compare alors la sortie avec la sortie attendue, telle que définie dans la docstring.

Le module unittest est un cadriciel un peu plus élaboré basé sur les cadriciels de test de Java et de Smalltalk.

Pour rendre le test plus aisé, il est nécessaire de bien découper le code d’un programme. Votre programme doit avoir la quasi-totalité des fonctionnalités dans des fonctions ou des classes — et ceci a parfois l’avantage aussi plaisant qu’inattendu de rendre le programme plus rapide, les accès aux variables locales étant en effet plus rapides que les accès aux variables globales. De plus le programme doit éviter au maximum de manipuler des variables globales, car ceci rend le test beaucoup plus difficile.

La « logique générale » d’un programme devrait être aussi simple que

if __name__ == "__main__":
    main_logic()

à la fin du module principal du programme.

Une fois que la logique du programme est implémentée par un ensemble de fonctions et de comportements de classes, il faut écrire des fonctions de test qui vont éprouver cette logique. À chaque module, il est possible d’associer une suite de tests qui joue de manière automatique un ensemble de tests. Au premier abord, il semble qu’il faille fournir un effort conséquent, mais comme Python est un langage concis et flexible, c’est surprenamment aisé. Écrire simultanément le code « de production » et les fonctions de test associées rend le développement plus agréable et plus amusant, car ceci permet de trouver des bogues, voire des défauts de conception, plus facilement.

Les « modules auxiliaires » qui n’ont pas vocation à être le module principal du programme peuvent inclure un test pour se vérifier eux-mêmes.

if __name__ == "__main__":
    self_test()

Les programmes qui interagissent avec des interfaces externes complexes peuvent être testés même quand ces interfaces ne sont pas disponibles, en utilisant des interfaces « simulacres » implémentées en Python.

Comment générer la documentation à partir des docstrings ?

Le module pydoc peut générer du HTML à partir des docstrings du code source Python. Il est aussi possible de documenter une API uniquement à partir des docstrings à l’aide de epydoc. Sphinx peut également inclure du contenu provenant de docstrings.

Comment détecter qu’une touche est pressée ?

For Unix variants there are several solutions. It’s straightforward to do this using curses, but curses is a fairly large module to learn. Here’s a solution without curses:

import termios, fcntl, sys, os
fd = sys.stdin.fileno()

oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)

oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)

try:
    while 1:
        try:
            c = sys.stdin.read(1)
            print "Got character", repr(c)
        except IOError: pass
finally:
    termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
    fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)

You need the termios and the fcntl module for any of this to work, and I’ve only tried it on Linux, though it should work elsewhere. In this code, characters are read and printed one at a time.

termios.tcsetattr() turns off stdin’s echoing and disables canonical mode. fcntl.fnctl() is used to obtain stdin’s file descriptor flags and modify them for non-blocking mode. Since reading stdin when it is empty results in an IOError, this error is caught and ignored.

Fils d’exécution

Comment programmer avec des fils d’exécution ?

Be sure to use the threading module and not the thread module. The threading module builds convenient abstractions on top of the low-level primitives provided by the thread module.

Un ensemble de diapositives issues du didacticiel de Aahz sur les fils d’exécution est disponible à http://www.pythoncraft.com/OSCON2001/.

Aucun de mes fils ne semble s’exécuter : pourquoi ?

Dès que le fil d’exécution principal se termine, tous les fils sont tués. Le fil principal s’exécute trop rapidement, sans laisser le temps aux autres fils de faire quoi que ce soit.

Une correction simple consiste à ajouter un temps d’attente suffisamment long à la fin du programme pour que tous les fils puissent se terminer :

import threading, time

def thread_task(name, n):
    for i in range(n): print name, i

for i in range(10):
    T = threading.Thread(target=thread_task, args=(str(i), i))
    T.start()

time.sleep(10) # <----------------------------!

Mais à présent, sur beaucoup de plates-formes, les fils ne s’exécutent pas en parallèle, mais semblent s’exécuter de manière séquentielle, l’un après l’autre ! En réalité, l’ordonnanceur de fils du système d’exploitation ne démarre pas de nouveau fil avant que le précédent ne soit bloqué.

Une correction simple consiste à ajouter un petit temps d’attente au début de la fonction :

def thread_task(name, n):
    time.sleep(0.001) # <---------------------!
    for i in range(n): print name, i

for i in range(10):
    T = threading.Thread(target=thread_task, args=(str(i), i))
    T.start()

time.sleep(10)

Instead of trying to guess a good delay value for time.sleep(), it’s better to use some kind of semaphore mechanism. One idea is to use the Queue module to create a queue object, let each thread append a token to the queue when it finishes, and let the main thread read as many tokens from the queue as there are threads.

Comment découper et répartir une tâche au sein d’un ensemble de fils d’exécutions ?

Use the Queue module to create a queue containing a list of jobs. The Queue class maintains a list of objects and has a .put(obj) method that adds items to the queue and a .get() method to return them. The class will take care of the locking necessary to ensure that each job is handed out exactly once.

Voici un exemple trivial :

import threading, Queue, time

# The worker thread gets jobs off the queue.  When the queue is empty, it
# assumes there will be no more work and exits.
# (Realistically workers will run until terminated.)
def worker():
    print 'Running worker'
    time.sleep(0.1)
    while True:
        try:
            arg = q.get(block=False)
        except Queue.Empty:
            print 'Worker', threading.currentThread(),
            print 'queue empty'
            break
        else:
            print 'Worker', threading.currentThread(),
            print 'running with argument', arg
            time.sleep(0.5)

# Create queue
q = Queue.Queue()

# Start a pool of 5 workers
for i in range(5):
    t = threading.Thread(target=worker, name='worker %i' % (i+1))
    t.start()

# Begin adding work to the queue
for i in range(50):
    q.put(i)

# Give threads time to run
print 'Main thread sleeping'
time.sleep(5)

Quand celui-ci est exécuté, il produit la sortie suivante :

Running worker
Running worker
Running worker
Running worker
Running worker
Main thread sleeping
Worker <Thread(worker 1, started)> running with argument 0
Worker <Thread(worker 2, started)> running with argument 1
Worker <Thread(worker 3, started)> running with argument 2
Worker <Thread(worker 4, started)> running with argument 3
Worker <Thread(worker 5, started)> running with argument 4
Worker <Thread(worker 1, started)> running with argument 5
...

Consult the module’s documentation for more details; the Queue class provides a featureful interface.

Quels types de mutations sur des variables globales sont compatibles avec les programmes à fils d’exécution multiples ? sécurisé ?

A global interpreter lock (GIL) is used internally to ensure that only one thread runs in the Python VM at a time. In general, Python offers to switch among threads only between bytecode instructions; how frequently it switches can be set via sys.setcheckinterval(). Each bytecode instruction and therefore all the C implementation code reached from each instruction is therefore atomic from the point of view of a Python program.

En théorie, cela veut dire qu’un décompte exact nécessite une connaissance parfaite de l’implémentation de la MVP. En pratique, cela veut dire que les opérations sur des variables partagées de type natif (les entier, les listes, les dictionnaires etc.) qui « semblent atomiques » le sont réellement.

Par exemple, les opérations suivantes sont toutes atomiques (L, L1 et L2 sont des listes, D, D1 et D2 sont des dictionnaires, x et y sont des objets, i et j des entiers) :

L.append(x)
L1.extend(L2)
x = L[i]
x = L.pop()
L1[i:j] = L2
L.sort()
x = y
x.field = y
D[x] = y
D1.update(D2)
D.keys()

Les suivantes ne le sont pas :

i = i+1
L.append(L[-1])
L[i] = L[j]
D[x] = D[x] + 1

Les opérations qui remplacent d’autres objets peuvent invoquer la méthode __del__() de ces objets quand leur compteur de référence passe à zéro, et cela peut avoir de l’impact. C’est tout particulièrement vrai pour les des changements massifs sur des dictionnaires ou des listes. En cas de doute, il vaut mieux utiliser un mutex.

Pourquoi ne pas se débarrasser du verrou global de l’interpréteur ?

Le verrou global de l’interpréteur (GIL) est souvent vu comme un obstacle au déploiement de code Python sur des serveurs puissants avec de nombreux processeurs, car un programme Python à fils d’exécutions multiples n’utilise en réalité qu’un seul processeur. Presque tout le code Python ne peut en effet être exécuté qu’avec le GIL acquis.

Back in the days of Python 1.5, Greg Stein actually implemented a comprehensive patch set (the « free threading » patches) that removed the GIL and replaced it with fine-grained locking. Unfortunately, even on Windows (where locks are very efficient) this ran ordinary Python code about twice as slow as the interpreter using the GIL. On Linux the performance loss was even worse because pthread locks aren’t as efficient.

Since then, the idea of getting rid of the GIL has occasionally come up but nobody has found a way to deal with the expected slowdown, and users who don’t use threads would not be happy if their code ran at half the speed. Greg’s free threading patch set has not been kept up-to-date for later Python versions.

This doesn’t mean that you can’t make good use of Python on multi-CPU machines! You just have to be creative with dividing the work up between multiple processes rather than multiple threads. Judicious use of C extensions will also help; if you use a C extension to perform a time-consuming task, the extension can release the GIL while the thread of execution is in the C code and allow other threads to get some work done.

On a déjà proposé de restreindre le GIL par interpréteur, et non plus d’être complétement global ; les interpréteurs ne seraient plus en mesure de partager des objets. Malheureusement, cela n’a pas beaucoup de chance non plus d’arriver. Cela nécessiterait un travail considérable, car la façon dont beaucoup d’objets sont implémentés rend leur état global. Par exemple, les entiers et les chaînes de caractères courts sont mis en cache ; ces caches devraient être déplacés au niveau de l’interpréteur. D’autres objets ont leur propre liste de suppression, ces listes devraient être déplacées au niveau de l’interpréteur et ainsi de suite.

C’est une tâche sans fin, car les extensions tierces ont le même problème, et il est probable que les extensions tierces soient développées plus vite qu’il ne soit possible de les corriger pour les faire stocker leur état au niveau de l’interpréteur et non plus au niveau global.

Et enfin, quel intérêt y-a t’il à avoir plusieurs interpréteurs qui ne partagent pas d’état, par rapport à faire tourner chaque interpréteur dans un processus différent ?

Les entrées/sorties

Comment supprimer un fichier ? (et autres questions sur les fichiers…)

Use os.remove(filename) or os.unlink(filename); for documentation, see the os module. The two functions are identical; unlink() is simply the name of the Unix system call for this function.

Utilisez os.rmdir() pour supprimer un dossier et os.mkdir() pour en créer un nouveau. os.makedirs(chemin) crée les dossiers intermédiaires de chemin qui n’existent pas et os.removedirs(chemin) supprime les dossiers intermédiaires si ceux-ci sont vides. Pour supprimer une arborescence et tout son contenu, utilisez shutil.rmtree().

os.rename(ancien_chemin, nouveau_chemin) permet de renommer un fichier.

To truncate a file, open it using f = open(filename, "r+"), and use f.truncate(offset); offset defaults to the current seek position. There’s also os.ftruncate(fd, offset) for files opened with os.open(), where fd is the file descriptor (a small integer).

Le module shutil propose aussi un grand nombre de fonctions pour effectuer des opérations sur des fichiers comme copyfile(), copytree() et rmtree().

Comment copier un fichier ?

Le module shutil fournit la fonction copyfile(). Sous MacOS 9, celle-ci ne copie pas le clonage de ressources ni les informations du chercheur.

Comment lire (ou écrire) des données binaires ?

Pour lire ou écrire des formats de données complexes en binaire, il est recommandé d’utiliser le module struct. Celui-ci permet de convertir une chaîne de caractères qui contient des données binaires, souvent des nombres, en objets Python, et vice-versa.

Par exemple, le code suivant lit, depuis un fichier, deux entiers codés sur 2 octets et un entier codé sur 4 octets, en format gros-boutiste :

import struct

f = open(filename, "rb")  # Open in binary mode for portability
s = f.read(8)
x, y, z = struct.unpack(">hhl", s)

« > » dans la chaîne de formatage indique que la donnée doit être lue en mode gros-boutiste, la lettre « h » indique un entier court (2 octets) et la lettre « l » indique un entier long (4 octets).

Pour une donnée plus régulière (p. ex. une liste homogène d’entiers ou de nombres à virgule flottante), il est possible d’utiliser le module array.

Il me semble impossible d’utiliser os.read() sur un tube créé avec os.popen() ; pourquoi ?

os.read() est une fonction de bas niveau qui prend en paramètre un descripteur de fichier — un entier court qui représente le fichier ouvert. os.popen() crée un objet fichier de haut niveau, du même type que celui renvoyé par la fonction native open(). Par conséquent, pour lire n octets d’un tube p créé avec os.popen(), il faut utiliser p.read(n).

How do I run a subprocess with pipes connected to both input and output?

Use the popen2 module. For example:

import popen2
fromchild, tochild = popen2.popen2("command")
tochild.write("input\n")
tochild.flush()
output = fromchild.readline()

Warning: in general it is unwise to do this because you can easily cause a deadlock where your process is blocked waiting for output from the child while the child is blocked waiting for input from you. This can be caused by the parent expecting the child to output more text than it does or by data being stuck in stdio buffers due to lack of flushing. The Python parent can of course explicitly flush the data it sends to the child before it reads any output, but if the child is a naive C program it may have been written to never explicitly flush its output, even if it is interactive, since flushing is normally automatic.

Note that a deadlock is also possible if you use popen3() to read stdout and stderr. If one of the two is too large for the internal buffer (increasing the buffer size does not help) and you read() the other one first, there is a deadlock, too.

Note on a bug in popen2: unless your program calls wait() or waitpid(), finished child processes are never removed, and eventually calls to popen2 will fail because of a limit on the number of child processes. Calling os.waitpid() with the os.WNOHANG option can prevent this; a good place to insert such a call would be before calling popen2 again.

In many cases, all you really need is to run some data through a command and get the result back. Unless the amount of data is very large, the easiest way to do this is to write it to a temporary file and run the command with that temporary file as input. The standard module tempfile exports a mktemp() function to generate unique temporary file names.

import tempfile
import os

class Popen3:
    """
    This is a deadlock-safe version of popen that returns
    an object with errorlevel, out (a string) and err (a string).
    (capturestderr may not work under windows.)
    Example: print Popen3('grep spam','\n\nhere spam\n\n').out
    """
    def __init__(self,command,input=None,capturestderr=None):
        outfile=tempfile.mktemp()
        command="( %s ) > %s" % (command,outfile)
        if input:
            infile=tempfile.mktemp()
            open(infile,"w").write(input)
            command=command+" <"+infile
        if capturestderr:
            errfile=tempfile.mktemp()
            command=command+" 2>"+errfile
        self.errorlevel=os.system(command) >> 8
        self.out=open(outfile,"r").read()
        os.remove(outfile)
        if input:
            os.remove(infile)
        if capturestderr:
            self.err=open(errfile,"r").read()
            os.remove(errfile)

Note that many interactive programs (e.g. vi) don’t work well with pipes substituted for standard input and output. You will have to use pseudo ttys (« ptys ») instead of pipes. Or you can use a Python interface to Don Libes” « expect » library. A Python extension that interfaces to expect is called « expy » and available from http://expectpy.sourceforge.net. A pure Python solution that works like expect is pexpect.

Comment accéder au port de transmission en série (RS-232) ?

Pour Win32, POSIX (Linux, BSD, etc.) et Jython :

Pour Unix, référez-vous à une publication sur Usenet de Mitch Chapman :

Pourquoi fermer sys.stdout, sys.stdin, sys.stderr ne les ferme pas réellement ?

Python file objects are a high-level layer of abstraction on top of C streams, which in turn are a medium-level layer of abstraction on top of (among other things) low-level C file descriptors.

For most file objects you create in Python via the built-in file constructor, f.close() marks the Python file object as being closed from Python’s point of view, and also arranges to close the underlying C stream. This also happens automatically in f’s destructor, when f becomes garbage.

But stdin, stdout and stderr are treated specially by Python, because of the special status also given to them by C. Running sys.stdout.close() marks the Python-level file object as being closed, but does not close the associated C stream.

To close the underlying C stream for one of these three, you should first be sure that’s what you really want to do (e.g., you may confuse extension modules trying to do I/O). If it is, use os.close:

os.close(0)   # close C's stdin stream
os.close(1)   # close C's stdout stream
os.close(2)   # close C's stderr stream

Programmation réseau et Internet

Quels sont les outils Python dédiés à la Toile ?

Référez-vous aux chapitres intitulés Gestion des protocoles internet et Traitement des données provenant d’Internet dans le manuel de référence de la bibliothèque. Python a de nombreux modules pour construire des applications de Toile côté client comme côté serveur.

Un résumé des cadriciels disponibles est maintenu par Paul Boddie à l’adresse https://wiki.python.org/moin/WebProgramming.

Cameron Laird maintient un ensemble intéressant d’articles sur les technologies Python dédiées à la Toile à l’adresse http://phaseit.net/claird/comp.lang.python/web_python.

Comment reproduire un envoi de formulaire CGI (METHOD=POST) ?

J’aimerais récupérer la page de retour d’un envoi de formulaire sur la Toile. Existe-t’il déjà du code qui pourrait m’aider à le faire facilement ?

Yes. Here’s a simple example that uses httplib:

#!/usr/local/bin/python

import httplib, sys, time

# build the query string
qs = "First=Josephine&MI=Q&Last=Public"

# connect and send the server a path
httpobj = httplib.HTTP('www.some-server.out-there', 80)
httpobj.putrequest('POST', '/cgi-bin/some-cgi-script')
# now generate the rest of the HTTP headers...
httpobj.putheader('Accept', '*/*')
httpobj.putheader('Connection', 'Keep-Alive')
httpobj.putheader('Content-type', 'application/x-www-form-urlencoded')
httpobj.putheader('Content-length', '%d' % len(qs))
httpobj.endheaders()
httpobj.send(qs)
# find out what the server said in response...
reply, msg, hdrs = httpobj.getreply()
if reply != 200:
    sys.stdout.write(httpobj.getfile().read())

Note that in general for percent-encoded POST operations, query strings must be quoted using urllib.urlencode(). For example, to send name=Guy Steele, Jr.:

>>> import urllib
>>> urllib.urlencode({'name': 'Guy Steele, Jr.'})
'name=Guy+Steele%2C+Jr.'

Quel module utiliser pour générer du HTML ?

La page wiki de la programmation Toile (en anglais) répertorie un ensemble de liens pertinents.

Comment envoyer un courriel avec un script Python ?

Utilisez le module smtplib de la bibliothèque standard.

Voici un exemple très simple d’un envoyeur de courriel qui l’utilise. Cette méthode fonctionne sur tous les serveurs qui implémentent SMTP.

import sys, smtplib

fromaddr = raw_input("From: ")
toaddrs  = raw_input("To: ").split(',')
print "Enter message, end with ^D:"
msg = ''
while True:
    line = sys.stdin.readline()
    if not line:
        break
    msg += line

# The actual mail send
server = smtplib.SMTP('localhost')
server.sendmail(fromaddr, toaddrs, msg)
server.quit()

Sous Unix, il est possible d’utiliser sendmail. La localisation de l’exécutable sendmail dépend du système ; cela peut-être /usr/lib/sendmail ou /usr/sbin/sendmail, la page de manuel de sendmail peut vous aider. Par exemple :

import os

SENDMAIL = "/usr/sbin/sendmail"  # sendmail location
p = os.popen("%s -t -i" % SENDMAIL, "w")
p.write("To: receiver@example.com\n")
p.write("Subject: test\n")
p.write("\n") # blank line separating headers from body
p.write("Some text\n")
p.write("some more text\n")
sts = p.close()
if sts != 0:
    print "Sendmail exit status", sts

Comment éviter de bloquer dans la méthode connect() d’un connecteur réseau ?

The select module is commonly used to help with asynchronous I/O on sockets.

Pour empêcher une connexion TCP de se bloquer, il est possible de mettre le connecteur en mode lecture seule. Avec cela, au moment du connect(), la connexion pourra être immédiate (peu probable) ou bien vous obtiendrez une exception qui contient le numéro d’erreur dans .errno. errno.EINPROGRESS indique que la connexion est en cours, mais qu’elle n’a pas encore aboutie. La valeur dépend du système d’exploitation, donc renseignez-vous sur la valeur utilisée par votre système.

You can use the connect_ex() method to avoid creating an exception. It will just return the errno value. To poll, you can call connect_ex() again later – 0 or errno.EISCONN indicate that you’re connected – or you can pass this socket to select to check if it’s writable.

Bases de données

Existe-t’il des modules Python pour s’interfacer avec des bases de données ?

Oui.

Python 2.3 includes the bsddb package which provides an interface to the BerkeleyDB library. Interfaces to disk-based hashes such as DBM and GDBM are also included with standard Python.

La gestion de la plupart des bases de données relationnelles est assurée. Voir la page wiki DatabaseProgramming pour plus de détails.

Comment implémenter la persistance d’objets en Python ?

The pickle library module solves this in a very general way (though you still can’t store things like open files, sockets or windows), and the shelve library module uses pickle and (g)dbm to create persistent mappings containing arbitrary Python objects. For better performance, you can use the cPickle module.

A more awkward way of doing things is to use pickle’s little sister, marshal. The marshal module provides very fast ways to store noncircular basic Python types to files and strings, and back again. Although marshal does not do fancy things like store instances or handle shared references properly, it does run extremely fast. For example, loading a half megabyte of data may take less than a third of a second. This often beats doing something more complex and general such as using gdbm with pickle/shelve.

Why is cPickle so slow?

By default pickle uses a relatively old and slow format for backward compatibility. You can however specify other protocol versions that are faster:

largeString = 'z' * (100 * 1024)
myPickle = cPickle.dumps(largeString, protocol=1)

If my program crashes with a bsddb (or anydbm) database open, it gets corrupted. How come?

Databases opened for write access with the bsddb module (and often by the anydbm module, since it will preferentially use bsddb) must explicitly be closed using the .close() method of the database. The underlying library caches database contents which need to be converted to on-disk form and written.

If you have initialized a new bsddb database but not written anything to it before the program crashes, you will often wind up with a zero-length file and encounter an exception the next time the file is opened.

I tried to open Berkeley DB file, but bsddb produces bsddb.error: (22, “Invalid argument”). Help! How can I restore my data?

Don’t panic! Your data is probably intact. The most frequent cause for the error is that you tried to open an earlier Berkeley DB file with a later version of the Berkeley DB library.

Many Linux systems now have all three versions of Berkeley DB available. If you are migrating from version 1 to a newer version use db_dump185 to dump a plain text version of the database. If you are migrating from version 2 to version 3 use db2_dump to create a plain text version of the database. In either case, use db_load to create a new native database for the latest version installed on your computer. If you have version 3 of Berkeley DB installed, you should be able to use db2_load to create a native version 2 database.

You should move away from Berkeley DB version 1 files because the hash file code contains known bugs that can corrupt your data.

Mathématiques et calcul numérique

Comment générer des nombres aléatoires en Python ?

Le module random de la bibliothèque standard comprend un générateur de nombres aléatoires. Son utilisation est simple :

import random
random.random()

Le code précédent renvoie un nombre à virgule flottante aléatoire dans l’intervalle [0, 1[.

Ce module fournit beaucoup d’autres générateurs spécialisés comme :

  • randrange(a, b) génère un entier dans l’intervalle [a, b[.

  • uniform(a, b) génère un nombre à virgule flottante aléatoire dans l’intervalle [a, b[.

  • normalvariate(mean, sdev) simule la loi normale (Gaussienne).

Des fonctions de haut niveau opèrent directement sur des séquences comme :

  • choice(S) sélectionne au hasard un élément d’une séquence donnée

  • shuffle(L) mélange une liste en-place, c-à-d lui applique une permutation aléatoire

Il existe aussi une classe Random qu’il est possible d’instancier pour créer des générateurs aléatoires indépendants.