Utilità Python

In questa sezione, esamineremo alcuni dei molti moduli di utilità standard di Python per risolvere problemi comuni.

File system: os, os.path, comandi

I moduli *os* e *os.path* includono molte funzioni per interagire con il file system. Il modulo *shutil* può copiare i file.

  • documenti del modulo OS
  • filenames = os.listdir(dir) - elenco di nomi di file nel percorso della directory (escluso . e ...). I nomi file sono solo i nomi contenuti nella directory, non i loro percorsi assoluti.
  • os.path.join(dir, filename): dato un nome file dall'elenco precedente, utilizzalo per unire dir e nome file in modo da creare un percorso
  • os.path. Abpath(path): dato un percorso, restituisce una forma assoluta, ad esempio /home/nick/foo/bar.html
  • os.path.dirname(path), os.path.basename(path): dato dir/foo/bar.html, restituisce il dirname "dir/foo" e il basename "bar.html"
  • os.path.exists(path) -- true se esiste
  • os.mkdir(dir_path) - crea una dir, os.makedirs(dir_path) rende tutte le directory necessarie in questo percorso
  • chiudiil.copy(percorso-origine, percorso-destinazione): copia un file (devono esistere le directory del percorso di destinazione)
## 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

Esplorare un modulo funziona bene con le funzioni incorporate di Python help() e dir(). Nell'interprete, esegui"import os", quindi utilizza questi comandi per vedere cosa è disponibile nel modulo: dir(os), help(os.listdir), dir(os.path), help(os.path.dirname).

Esecuzione di processi esterni - sottoprocesso

Il modulo *subprocess* è un modo semplice per eseguire un comando esterno e acquisirne l'output.

  • documenti dei moduli per i processi secondari
  • output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) esegue il comando, attende l'uscita e restituisce il testo di output. Il comando viene eseguito con l'output standard e l'errore standard combinati nell'unico testo di output. Se l'operazione non va a buon fine, viene generato un errore CalledProcessError.
  • Se vuoi avere un maggiore controllo sull'esecuzione del processo secondario, consulta la classe subprocess.popen.
  • Esiste anche un semplice subprocess.call(cmd) che esegue il comando, scarica l'output nell'output e restituisce il codice di errore. Funziona se vuoi eseguire il comando ma non hai bisogno di acquisirne l'output nelle strutture di dati 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

Eccezioni

Un'eccezione rappresenta un errore di runtime che interrompe l'esecuzione normale su una determinata riga e trasferisce il controllo al codice di gestione degli errori. Questa sezione presenta solo gli utilizzi più basilari delle eccezioni. Ad esempio, un errore di runtime potrebbe essere dovuto al fatto che una variabile utilizzata nel programma non ha un valore (ValueError, probabilmente l'averai notato alcune volte) o un errore relativo all'apertura di un file perché un file non esiste (IOError). Scopri di più nel tutorial sulle eccezioni e consulta l'elenco completo delle eccezioni.

Senza alcun codice per la gestione degli errori (come abbiamo fatto finora), un'eccezione di runtime chiude il programma con un messaggio di errore. Si tratta di un buon comportamento predefinito, che hai notato molte volte. Puoi aggiungere una struttura di tipo "prova/eccezione" al codice per gestire le eccezioni, ad esempio:

  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 sezione prova: include il codice che potrebbe generare un'eccezione. La sezione tranne: contiene il codice da eseguire in caso di eccezione. Se non ci sono eccezioni, la sezione tranne: viene saltata (vale a dire, il codice serve solo per la gestione degli errori e non il caso "normale" per il codice). Puoi ottenere un puntatore all'oggetto eccezione stesso con la sintassi "except IOError as e: .." (e punta all'oggetto eccezione).

HTTP -- urllib e urlparse

Il modulo *urllib.request* fornisce il recupero dell'URL, facendo in modo che un URL assomigli a un file che puoi leggere. Il modulo *urlparse* può scomporre e mettere insieme gli URL.

  • documenti del modulo urllib.request
  • ufile = urllib.request.urlopen(url) -- restituisce un file simile a questo oggetto per l'URL in questione.
  • text = ufile.read() -- può leggere da esso, come un file (readlines() ecc. funzionano anche)
  • info = ufile.info() -- Le informazioni meta per la richiesta. info.gettype() è il tipo MIME, ad esempio "text/html"
  • baseurl = ufile.geturl(): ottiene l'URL "base" della richiesta, che potrebbe essere diverso dall'originale a causa dei reindirizzamenti
  • urllib.request.urlretrieve(url, nome file): scarica i dati dell'URL nel percorso del file specificato.
  • urllib.parse.urljoin(baseurl, url): dato un URL che potrebbe o meno essere completo e l'URL base della pagina da cui proviene, restituiscono un URL completo. Utilizza geturl() sopra per fornire l'URL di base.

Tutte le eccezioni sono indicate nel formato 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)

Il codice sopra riportato funziona bene, ma non include la gestione degli errori se per qualche motivo un URL non funziona. Di seguito è riportata una versione della funzione che aggiunge la logica di prova/eccezione per stampare un messaggio di errore se l'operazione sull'URL non riesce.

Se urlopen() sembra essere inutilizzato, il sistema potrebbe non consentire l'accesso diretto ad alcuni indirizzi HTTP. Puoi verificarlo provando a recuperare lo stesso URL utilizzando wget o curl. Se anche questi programmi non risolvono il problema, dovrai recuperare i contenuti http attraverso un servizio proxy. La configurazione dell'accesso proxy non è trattata da questo tutorial.

## 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)

Allenamento

Per esercitarti con il file system e con il materiale dei comandi esterni, vedi Copia esercizio speciale. Per esercitarti con il materiale urllib, vedi l'esercizio con puzzle su log.