Utilitaires Python

Dans cette section, nous allons étudier quelques-uns des nombreux modules utilitaires standards de Python, qui permettent de résoudre des problèmes courants.

Système de fichiers : os, os.path, stopil

Les modules *os* et *os.path* incluent de nombreuses fonctions permettant d'interagir avec le système de fichiers. Le module *shutil* peut copier des fichiers.

  • documentation sur le module os
  • names = os.listdir(dir) -- liste des noms de fichiers dans ce chemin de répertoire (à l'exception de . et ..). Les noms de fichiers ne sont que les noms du répertoire, pas leurs chemins d'accès absolus.
  • os.path.join(dir, nom de fichier) : pour un nom de fichier de la liste ci-dessus, utilisez-le pour regrouper le répertoire et le nom de fichier afin de créer un chemin d'accès.
  • os.path.abspath(chemin) : à partir d'un chemin, renvoie une forme absolue, par exemple /home/nick/foo/bar.html.
  • os.path.dirname(chemin), os.path.basename(chemin) : à partir de dir/foo/bar.html, renvoie le nom de répertoire "dir/foo" et le nom de base "bar.html"
  • os.path.exists(path) : vrai s'il existe
  • os.mkdir(dir_path) : crée un seul répertoire, os.makedirs(dir_path) crée tous les répertoires nécessaires dans ce chemin
  • stopil.copy(source-path, dest-path) : copie d'un fichier (les répertoires du chemin d'accès doivent exister).
## Example pulls filenames from a dir, prints their relative and absolute paths
def printdir(dir):
  filenames = os.listdir(dir)
  for filename in filenames:
    print(filename)  ## foo.txt
    print(os.path.join(dir, filename)) ## dir/foo.txt (relative to current dir)
    print(os.path.abspath(os.path.join(dir, filename))) ## /home/nick/dir/foo.txt

L'exploration d'un module fonctionne bien avec les fonctions Python help() et dir() intégrées. Dans l'interpréteur, exécutez une commande"import os", puis utilisez ces commandes pour rechercher les éléments disponibles dans le module: dir(os), help(os.listdir), dir(os.path), help(os.path.dirname).

Exécution de processus externes -- sous-processus

Le module *subprocess* est un moyen simple d'exécuter une commande externe et de capturer sa sortie.

  • Documentation sur le module de sous-traitance
  • sortie = subprocess.check_output(cmd, stderr=subprocess.STDOUT) : exécute la commande, attend qu'elle se ferme et renvoie son texte de sortie. La commande est exécutée avec sa sortie standard et son erreur standard combinées en un seul texte de sortie. En cas d'échec, une erreur CalledProcessError est générée.
  • Si vous souhaitez mieux contrôler l'exécution du sous-processus, consultez la classe subprocess.popen.
  • Il existe également un simple subprocess.call(cmd) qui exécute la commande, vide sa sortie sur votre sortie et renvoie son code d'erreur. Cela fonctionne si vous souhaitez exécuter la commande, mais que vous n'avez pas besoin de capturer sa sortie dans vos structures de données Python.
import subprocess

## Given a dir path, run an external 'ls -l' on it --
## shows how to call an external program
def listdir(dir):
  cmd = 'ls -l ' + dir
  print("Command to run:", cmd)   ## good to debug cmd before actually running it
  (status, output) = subprocess.getstatusoutput(cmd)
  if status:    ## Error case, print the command's output to stderr and exit
    sys.stderr.write(output)
    sys.exit(status)
  print(output)  ## Otherwise do something with the command's output

Exceptions

Une exception représente une erreur d'exécution qui interrompt l'exécution normale sur une ligne particulière et transfère le contrôle au code de gestion des erreurs. Cette section présente simplement les utilisations les plus élémentaires des exceptions. Par exemple, une erreur d'exécution peut être due à l'absence de valeur d'une variable utilisée dans le programme (ValueError .. vous l'avez probablement constaté plusieurs fois), ou une erreur d'opération d'ouverture de fichier due à l'absence de fichier (IOError). Pour en savoir plus, consultez le tutoriel sur les exceptions et la liste complète des exceptions.

Sans code de gestion des erreurs (comme nous l'avons fait jusqu'à présent), une exception d'exécution interrompt simplement le programme avec un message d'erreur. Il s'agit d'un bon comportement par défaut, que vous avez constaté à de nombreuses reprises. Vous pouvez ajouter une structure "try/except" à votre code pour gérer les exceptions, comme ceci:

  try:
    ## Either of these two lines could throw an IOError, say
    ## if the file does not exist or the read() encounters a low level error.
    f = open(filename, 'rb')
    data = f.read()
    f.close()
  except IOError:
    ## Control jumps directly to here if any of the above lines throws IOError.
    sys.stderr.write('problem reading:' + filename)
  ## In any case, the code then continues with the line after the try/except

La section try: inclut le code qui peut générer une exception. La section except: contient le code à exécuter en cas d'exception. S'il n'y a pas d'exception, la section "sauf:" est ignorée (c'est-à-dire que ce code ne concerne que la gestion des erreurs, et non le cas "normal" pour le code). Vous pouvez obtenir un pointeur vers l'objet d'exception lui-même à l'aide de la syntaxe "sauf IOError as e: .." (le e pointe vers l'objet d'exception).

HTTP : urllib et urlparse

Le module *urllib.request* permet d'extraire les URL, afin que l'URL ressemble à un fichier lisible. Le module *urlparse* peut démonter et assembler des URL.

  • Documentation sur le module urllib.request
  • ufile = urllib.request.urlopen(url) : renvoie un fichier semblable à un objet pour cette URL
  • text = ufile.read() -- peut le lire, comme un fichier (readlines(), etc.).
  • info = ufile.info() : méta-informations de cette requête. info.gettype() est le type MIME, par exemple "text/html".
  • baseurl = ufile.geturl() -- récupère l'URL "de base" de la requête, qui peut être différente de l'originale en raison de redirections
  • urllib.request.urlretrieve(url, username) : télécharge les données de l'URL vers le chemin d'accès au fichier donné.
  • urllib.parse.urljoin(baseurl, url) : à partir d'une URL complète ou non et de l'URL de base de la page d'où elle provient, renvoie une URL complète. Utilisez geturl() ci-dessus pour fournir l'URL de base.

Toutes les exceptions se trouvent dans urllib.error.

from urllib.request import urlopen

## Given a url, try to retrieve it. If it's text/html,
## print its base url and its text.
def wget(url):
  ufile = urlopen(url)  ## get file-like object for url
  info = ufile.info()   ## meta-info about the url content
  if info.get_content_type() == 'text/html':
    print('base url:' + ufile.geturl())
    text = ufile.read()  ## read all its text
    print(text)

Le code ci-dessus fonctionne correctement, mais il n'inclut pas de gestion des erreurs si une URL ne fonctionne pas pour une raison quelconque. Voici une version de la fonction qui ajoute une logique try/sauf pour afficher un message d'erreur si l'opération d'URL échoue.

Si urlopen() semble être bloqué, votre système n'autorise peut-être pas l'accès direct à certaines adresses HTTP. Vous pouvez le vérifier en essayant de récupérer la même URL à l'aide de wget ou de curl. Si ces programmes échouent également, vous devrez récupérer le contenu HTTP via un service proxy. La configuration de l'accès proxy n'est pas abordée dans ce tutoriel.

## Version that uses try/except to print an error message if the
## urlopen() fails.
def wget2(url):
  try:
    ufile = urlopen(url)
    if ufile.info().get_content_type() == 'text/html':
      print(ufile.read())
  except IOError:
    print('problem reading url:', url)

Exercice

Pour vous entraîner à utiliser le système de fichiers et les commandes externes, consultez l'article Copier l'exercice spécial. Pour vous entraîner à utiliser les ressources urllib, consultez l'exercice de réflexion sur les journaux.