4.14. Il modulo os

Il modulo os ha molte funzioni utili per manipolare file e processi e os.path ha molte funzioni per manipolare percorsi di file e directory.

Esempio 4.35. Costruire pathnames

>>> import os
>>> os.path.join("c:\\music\\ap\\", "mahadeva.mp3") 1 2
'c:\\music\\ap\\mahadeva.mp3'
>>> os.path.join("c:\\music\\ap", "mahadeva.mp3")   3
'c:\\music\\ap\\mahadeva.mp3'
>>> os.path.expanduser("~")                         4
'c:\\Documents and Settings\\mpilgrim\\My Documents'
>>> os.path.join(os.path.expanduser("~"), "Python") 5
'c:\\Documents and Settings\\mpilgrim\\My Documents\\Python'
1 os.path è un riferimento ad un modulo che dipende dalla piattaforma sulla quale lavorate. Proprio come getpass considera le differenze fra le piattaforme, impostando getpass ad una funzione specifica, anche os ne tiene conto impostando path come un modulo specifico per piattaforma in uso.
2 La funzione join di os.path costruisce un pathname a partire da uno o più pathname parziali. In questo semplice caso, si limita a concatenare delle stringhe. (Notate che occuparsi di pathname su Windows è odioso a causa del fatto che il carattere backslash deve essere escapato.)
3 Il questo esempio un po' banale, join aggiungerà un backslash extra al pathname prima di unirlo al nome del file. Ero contentissimo quando lo scoprii, dato che addSlashIfNecessary è una delle piccole e stupide funzioni che devo sempre scrivere, quando costruisco la mia toolbox in un nuovo linguaggio. Non scrivete queste piccole e stupide funzioni in Python; qualcun altro se ne è già occupato per voi.
4 expanduser espanderà un pathname che usa ~ per rappresentare la home directory dell'utente attuale. Questo funziona su ogni piattaforma ove gli utenti hanno una home directory, come Windows, UNIX e Mac OS X, non ha effetto su Mac OS.
5 Combinando queste tecniche, potete facilmente costruire percorsi per directory e file sotto la home directory dell'utente.

Esempio 4.36. Dividere i pathnames

>>> os.path.split("c:\\music\\ap\\mahadeva.mp3")                        1
('c:\\music\\ap', 'mahadeva.mp3')
>>> (filepath, filename) = os.path.split("c:\\music\\ap\\mahadeva.mp3") 2
>>> filepath                                                            3
'c:\\music\\ap'
>>> filename                                                            4
'mahadeva.mp3'
>>> (shortname, extension) = os.path.splitext(filename)                 5
>>> shortname
'mahadeva'
>>> extension
'.mp3'
1 La funzione split divide un pathname completo e ritorna una tupla contenente il percorso ed il nome del file. Ricordate quando dissi che potevate usare assegnamenti multi-variabile per ritornare valori multipli da una funzione? Bene, split è una di queste funzioni.
2 Assegnamo il valore di ritorno della funzione split ad una tupla di due variabili. Ogni variabile riceve il valore dell'elemento corrispondente dalla tupla ritornata.
3 La prima variabile, filepath, riceve il valore del primo elemento della tupla ritornata da split, il percorso del file.
4 La seconda variabile, filename, riceve il valore del secondo elemento della tupla ritornata da split, il nome del file.
5 os.path contiene anche una funzione splitext, che divide il nome di un file e ritorna una tupla contenente il nome del file e la sua estensione. Usiamo la stessa tecnica per assegnare ognuno di questi a variabili separate.

Esempio 4.37. Elencare directory

>>> os.listdir("c:\\music\\_singles\\")                                          1
['a_time_long_forgotten_con.mp3', 'hellraiser.mp3', 'kairo.mp3',
'long_way_home1.mp3', 'sidewinder.mp3', 'spinning.mp3']
>>> dirname = "c:\\"
>>> os.listdir(dirname)                                                          2
['AUTOEXEC.BAT', 'boot.ini', 'CONFIG.SYS', 'cygwin', 'docbook',
'Documents and Settings', 'Incoming', 'Inetpub', 'IO.SYS', 'MSDOS.SYS', 'Music',
'NTDETECT.COM', 'ntldr', 'pagefile.sys', 'Program Files', 'Python20', 'RECYCLER',
'System Volume Information', 'TEMP', 'WINNT']
>>> [f for f in os.listdir(dirname) if os.path.isfile(os.path.join(dirname, f))] 3
['AUTOEXEC.BAT', 'boot.ini', 'CONFIG.SYS', 'IO.SYS', 'MSDOS.SYS',
'NTDETECT.COM', 'ntldr', 'pagefile.sys']
>>> [f for f in os.listdir(dirname) if os.path.isdir(os.path.join(dirname, f))]  4
['cygwin', 'docbook', 'Documents and Settings', 'Incoming',
'Inetpub', 'Music', 'Program Files', 'Python20', 'RECYCLER',
'System Volume Information', 'TEMP', 'WINNT']
1 La funzione listdir prende un pathname e ritorna una lista del contenuto della directory.
2 listdir ritorna sia file che directory, senza indicare quale sia.
3 Potete usare il list filtering e la funzione isfile del modulo os.path per separare i file dalle directory. isfile prende un pathname e ritorna 1, nel caso in cui il percorso rappresenti un file e 0 altrimenti. Qui stiamo usando os.path.join per assicurarci un pathname completo, ma isfile funziona anche con un percorso parziale, relativo alla directory corrente. Potete usare os.getcwd() per ottenere la directory corrente.
4 os.path ha anche una funzione isdir che ritorna 1 se il percorso rappresenta una directory e 0 altrimenti. Potete usarla per ottenere la lista delle sottodirectory di un percorso.

Esempio 4.38. Elencare directory in fileinfo.py


def listDirectory(directory, fileExtList):                                        
    "get list of file info objects for files of particular extensions"
    fileList = [os.path.normcase(f) for f in os.listdir(directory)]               
    fileList = [os.path.join(directory, f) for f in fileList \
                if os.path.splitext(f)[1] in fileExtList]                         

Queste due linee di codice fanno tutto ciò che abbiamo imparato finora sul modulo os e anche qualcos'altro.

  1. os.listdir(directory) ritorna una lista di tutti i file compresi in directory.
  2. Iterando nella lista con f, usiamo os.path.normcase(f) per normalizzare il nome del file o della directory, in accordo al comportamento predefinito del sistema operativo in uso. normcase è una piccola ed utile funzione che rimedia al fatto che i sistemi operativi case-insensitive pensino che mahadeva.mp3 e mahadeva.MP3 siano lo stesso file. Per esempio, su Windows e Mac OS, normcase convertirà l'intero filename in caratteri minuscoli; sui sistemi UNIX-compatibili, ritornerà il nome del file invariato.
  3. Iterando attraverso la lista normalizzata, ancora con f, usiamo os.path.splitext(f) per dividere ogni nome di file dalla sua estensione.
  4. Per ogni file, vediamo se l'estensione è presente nella lista delle estensioni di cui stiamo tenendo conto (fileExtList, che è stata passata alla funzione listDirectory).
  5. Per ogni file trovato, usiamo os.path.join(directory, f) per costruire il percorso completo del file e ritornare una lista dei percorsi completi.
Nota
Ogniqualvolta sia possibile, dovreste usare le funzioni in os e os.path per file, directory e manipolazione dei percorsi. Questi moduli sono dei wrapper ai moduli specifici per piattaforma, per cui funzioni come os.path.split funzionano su UNIX, Windows, Mac OS ed ogni altra possibile piattaforma supportata da Python.

Ulteriori letture