| CodesReseau |
UserPreferences |
| Wiki Python Fr | FrontPage | RecentChanges | TitleIndex | WordIndex | SiteNavigation | HelpContents | moin.sf.net |
Pyro
Python Remote Objects, pour développer une application client serveur en appelant des classes distantes comme si elles étaient locales (un peu comme RMI pour Java)
Twisted Python
Twisted Python est un framework qui devrait simplifier la programmation reseau avec Python:
Rien de plus facile que d'envoyer un fichier par FTP:
1 2 3 4 5 6 7 8 | #!/usr/bin/env python
import ftplib # On importe le module FTP de Python
session = ftplib.FTP('212.12.34.56','sebsauvage','batman') # On se connecte au serveur (serveur, login, mot de passe)
monfichier = open('toto.txt','rb') # On ouvre le fichier à envoyer
session.storbinary('STOR toto.txt', monfichier) # On envoie le fichier
monfichier.close() # On ferme le fichier
session.quit() # On se déconnecte |
Vous avez bien entendu à votre disposition toutes les autres commandes FTP (lister un répertoire, changer de répertoire, reprendre un téléchargement interrompu, renommer un fichier...) dans le module ftplib. (Voir http://python.org/doc/current/lib/ftp-objects.html)
1 2 3 4 5 6 7 8 9 10 | #!/usr/bin/env python
from BaseHTTPServer import HTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
import os
os.chdir('/home/oli/dev/python/httpserver') # le répertoire où les pages html seront stockées.
serv = HTTPServer( ("", 10080), SimpleHTTPRequestHandler)
serv.serve_forever() |
Dans ce répertoire, vous placer un fichier index.html, ainsi que toutes les autres pages.
Avant dernière ligne: 10080 est le port réseau utilisé. Les ports inférieurs ou égaux à 1024 ne sont utilisables que par root.
PS: très pratique pour échanger des fichiers de machines à machines lorsque FTP n'est pas disponible.
Une article plus complet est disponible a cette adresse:
http://etudiant.epita.fr/~duponc_j/articles/webinterface.html
http://sebsauvage.net/python/newsarchiver.py
En lançant ce script tous les jours, vous pouvez ainsi archiver tous les messages d'un forum.
Vous trouverez dans la documentation de Python un exemple de serveur et client socket très simple: http://docs.python.org/lib/socket-example.html
Le serveur se met en écoute sur le port 50007, et le client vient s'y connecter pour écrire "Hello, world". Le serveur renvoie cette chaîne au client.
Par défaut, l'utilisation de sockets est bloquant (lors d'un .recv() par exemple).
Pour travailler avec des sockets non bloquants, vous avez 2 solutions:
Chaque solution a ses avantages.
Les sockets asynchrones sont intéressants quand votre goulot d'étranglement est le débit réseau.
Les threads sont intéressants quand votre goulot d'étranglement est le traitement CPU.
Voici un article en anglais avec des exemples pour chacune de ces méthodes: http://www.onlamp.com/pub/a/python/2004/02/12/advanced_nio.html
Pour faire des sockets asynchrone, vous pouvez utiliser les module asyncore et asynchat de Python. Notez qu'il existe des frameworks qui simplifient l'utilisation des sockets asynchrone, tels que Twisted
http://www.twistedmatrix.com/.
Pour les threads, le module thread de Python est à votre disposition. Le module threading vous offre même une interface de plus haut niveau, plus simple à manipuler.
Les modules urllib et urllib2 vous permettent de faire des requêtes HTTP.
urllib2 s'utilise de la même façon qu'urllib, mais il supporte également les proxy, avec ou sans mot de passe.
Voici comment l'utiliser. (Code inspiré de
http://groups.google.com/groups?selm=mailman.983901970.11969.python-list%40python.org)
1 2 3 4 5 6 7 8 9 10 11 12 | proxy_info = { 'host' : 'netcache.monentreprise.com',
'port' : 3128
}
# On créé un handler pour le proxy:
proxy_support = urllib2.ProxyHandler({"http" : "http://%(host)s:%(port)d" % proxy_info})
# On créé un opener utilisant ce handler:
opener = urllib2.build_opener(proxy_support)
# Puis on installe cet opener comme opener par défaut du module urllib2.
urllib2.install_opener(opener)
# Et on peut alors lancer nos requêtes HTTP:
pagehtml = urllib2.urlopen("http://wikipython.flibuste.net/").read() |
C'est presque la même chose, mais on ajoute login et mot de passe:
1 2 3 4 5 6 7 8 9 10 11 | proxy_info = { 'host' : 'netcache.monentreprise.com',
'port' : 3128,
'user' : 'gaston lagaffe',
'pass' : 'jeanne55'
}
proxy_support = urllib2.ProxyHandler({"http" : "http://%(user)s:%(pass)s@%(host)s:%(port)d" % proxy_info})
opener = urllib2.build_opener(proxy_support)
urllib2.install_opener(opener)
# Et on peut alors lancer nos requêtes HTTP:
pagehtml = urllib2.urlopen("http://wikipython.flibuste.net/").read() |
Modification : urllib2 ne semble pas fonctionner avec l'authentification proxy. Ceci est apparemment un bug connu. La librairie pycurl est la plus avancée sur ce sujet
Note de sebsauvage: Si si ça marche, j'utilise urllib2 avec proxy (et login/mot de passe) sans problème dans webGobbler (http://sebsauvage.net/webgobbler). Notez qu'il existe plusieurs méthodes d'authentification pour les proxy HTTP: Basic, Digest, NTLM... En Python 2.4.1, urllib2 supporte 2 authentifications: Basic et Digest. Si votre proxy ne supporte que NTLM (protocole Microsoft, supporté par Internet Explorer), vous n'avez pas de chance.
La methode precedente ne fonctionne pas sur mon proxy: (authentification via un serveur de domaine NT), j'ai donc implementé un Handler Basic d'Authentification (Proxy compatible heureusement) au lieu du Handler de Proxy standard. Pour ceux dont le proxy est compatible Digest choisir ProxyDigestAuthHandler.
1 2 3 4 5 6 7 8 9 | import urllib2
passwdMgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
passwdMgr.add_password(None, "proxy:8080", r"DOMAINE\jvacher", "monpassamoi")
opener = urllib2.build_opener(urllib2.ProxyBasicAuthHandler(passwdMgr))
urllib2.install_opener(opener)
pagehtml = urllib2.urlopen("http://wikipython.flibuste.net/").read()
print pagehtml |
Voilà j'éspère que cela en aidera certains. Jérôme Vacher alias jerrykhan
En principe, si vous avez créé une application qui envoie des requêtes HTTP, la netiquette dit qu'elle devrait s'identifier proprement dans le champ "User-Agent" des requêtes HTTP.
Par défaut, Python utilise le User-Agent Python-urllib/1.16
Voici comment mettre votre propre User-Agent:
1 2 3 4 | #! python
request_headers = { 'User-Agent': 'PeekABoo/1.3.7' }
request = urllib2.Request('http://sebsauvage.net', None, request_headers)
urlfile = urllib2.urlopen(request) |
En règle générale:
Voici comment gérer les codes d'erreur HTTP (404 et autres) avec urllib2:
1 2 3 4 5 6 7 8 9 10 | #! python
try:
urlfile = urllib2.urlopen('http://sebsauvage.net/nonexistingpage.html')
except urllib2.HTTPError, exc:
if exc.code == 404:
print "Page non trouvée !"
else:
print "La requête HTTP a échoué avec le code %d (%s)" % (exc.code, exc.msg)
except urllib2.URLError, exc:
print "Echec. Cause:", exc.reason |
De cette manière, vous pouvez tester les 404 et autres codes d'erreur HTTP. Notez que urllib2 ne lèvera pas d'exception pour les codes 2xx et 3xx. L'exception urllib2.HTTPError sera levée pour les codes 4xx et 5xx (ce qui est le comportement attendu).
Notez également que les codes de redirection 30x sont gérés automatiquement et de manière transparente par urllib2.
Quand vous envoyez une requête HTTP, elle peut retourner du HTML, des images, des fichiers zip... Par exemple, une requête comme http: //toto.com/image.gif peut très bien retourner du HTML ! Il est nécessaire de contrôller le type des données que vous recevez.
Il suffit de regarder dans le champ "Content-type" des entêtes HTTP de réponse. Par exemple:
1 2 3 | #! python
urlfile = urllib2.urlopen('http://www.commentcamarche.net/')
print "Le type de document est", urlfile.info().getheader("Content-Type","") |
Ce qui donne par exemple:
Le type de document est text/html
Mais attention, il arrive qu'il y ait des informations supplémentaires, telles que:
Le type de document est text/html; charset=iso-8859-1
Donc je vous recommande d'utiliser systématiquement:
1 2 | #! python
print "Document type is", urlfile.info().getheader("Content-Type","").split(';')[0].strip() |
pour être sûr de bien récupérer le Content-type seul.
Notez que .info() vous donnera les autres entêtes réponse HTTP:
1 2 3 | #! python print "HTTP Response headers:" print urlfile.info() |
Document type is Date: Thu, 23 Mar 2006 15:13:29 GMT Content-Type: text/html; charset=iso-8859-1 Server: Apache X-Powered-By: PHP/5.1.2-1.dotdeb.2 Connection: close
Depuis la version 2.4, Python contient le module cookielib qui peut gérer automatiquement les cookies.
(Notez qu'il est possible d'avoir une gestion des cookies dans les versions précédentes de Python avec des modules séparés tels que ClientCookie).
Les cookies sont utile pour parcourir les sites qui nécessite un login/password: Ces sites gèrent habituellement les sessions avec un cookie.
Voici un exemple: Se loguer sur le site imdb.com:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #! python
import cookielib, urllib, urllib2
login = 'ismellbacon123@yahoo.com'
password = 'login'
# On active le support des cookies pour urllib2
cookiejar = cookielib.CookieJar()
urlOpener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))
# On envoie login/password au site qui nous renvoie un cookie de session
values = {'login':login, 'password':password }
data = urllib.urlencode(values)
request = urllib2.Request("http://www.imdb.com/register/login", data)
url = urlOpener.open(request) # Notre cookiejar reçoit automatiquement les cookies
page = url.read(500000)
# On s'assure qu'on est bien logué en vérifiant la présence du cookie "id"
# (qui est - sur le site imdb.com - le cookie contenant l'identifiant de session.)
if not 'id' in [cookie.name for cookie in cookiejar]:
raise ValueError, "Echec connexion avec login=%s, mot de passe=%s" % (login,password)
print "Nous sommes connecte !"
# Maintenant on fait une autre requête sur le site avec notre cookie de session.
# (Notre urlOpener utilise automatiquement les cookies de notre cookiejar)
url = urlOpener.open('http://imdb.com/find?s=all&q=grave')
page = url.read(200000) |
Il n'est généralement pas utile de vous déloguer.