os.path - Manipolare i nomi dei file indipendentemente dalla piattaforma

Scopo Elaborare, costruire, controllare ed altro sui nomi di file e percorsi
Versione Python 1.4 e superiore

Scrivere codice per lavorare con file su multiple piattaforme è facile se si usano le funzioni comprese nel modulo os.path. Anche i programmi che non si intende portare su diverse piattaforme dovrebbero usare os.path per rendere affidabile l'elaborazione dei percorsi.

Elaborare i Percorsi

Il primo gruppo di funzioni in os.path può essere usato per elaborare delle stringhe che rappresentano dei nomi di file dividendole nelle parti che li compongono. E' importante capire che queste funzioni non dipendono dal fatto che questi percorsi esistano. Esse operano solamente sulle stringhe.

L'elaborazione dei percorsi dipende da un pugno di variabili definite nel modulo os:

  • os.sep - Il separatore tra le porzioni del percorso (es. "/").
  • os.extsep - Il separatore tra il nome del file e la sua "estensione" (es. ".").
  • os.pardir - Il componente del percorso che serve per risalire l'albero delle directory su di un livello (es. "..").
  • os.curdir - Il componente del percorso che fa riferimento alla directory corrente (es. ".").
  • split() spezza il percorso in due parti separate e restituisce la tuple. Il secondo elemento è l'ultimo componente del percorso, ed il primo elemento è tutto quello che lo precede
import os.path

for path in [ '/uno/due/tre/
              '/uno/due/tre/',
              '/',
              '.',
              '']:
    print '"%s" : "%s"' % (path, os.path.split(path))
$ python ospath_split.py
"/uno/due/tre" : "('/uno/due', 'tre')"
"/uno/due/tre/" : "('/one/two/tre', '')"
"/" : "('/', '')"
"." : "('', '.')"
"" : "('', '')"

basename() restituisce un valore che equivale alla seconda parte del risultato di split().

import os.path

for path in [ '/uno/due/tre',
              '/uno/due/tre/',
              '/',
              '.',
              '']:
    print '"%s" : "%s"' % (path, os.path.basename(path))
$ python ospath_basename.py
"/uno/due/tre" : "tre"
"/uno/due/tre/" : ""
"/" : ""
"." : "."
"" : ""

dirname() ritorna il percorso che equivale alla prima parte del risultato di split()

import os.path

for path in [ '/uno/due/tre',
              '/uno/due/tre/',
              '/',
              '.',
              '']:
    print '"%s" : "%s"' % (path, os.path.dirname(path))
$ python ospath_dirname.py
"/uno/due/tre" : "/uno/due"
"/uno/due/tre/" : "/uno/due/tre"
"/" : "/"
"." : ""
"" : ""

splitext() funziona come split() ma divide il percorso sul separatore di estensione, invece che sui nomi di directory.

import os.path

for path in [ 'nomefile.txt', 'nomefile', '/percorso/al/nomefile.txt', '/', '' ]:
    print '"%s" :' % path, os.path.splitext(path)
$ python ospath_splitext.py
"nomefile.txt" : ('nomefile', '.txt')
"nomefile" : ('nomefile', '')
"/percorso/al/nomefile.txt" : ('/percorso/al/nomefile', '.txt')
"/" : ('/', '')
"" : ('', '')

commonprefix() prende una lista di percorsi come parametro e restituisce una singola stringa che rappresenta un prefisso comune presente in tutti i percorsi. Il valore potrebbe rappresentare un percorso che in realtà non esiste, ed il separatore di percorso non viene considerato, quindi il prefisso potrebbe non fermarsi nei confini del separatore.

import os.path

paths = ['/uno/due/tre/quattro',
         '/uno/due/trequalchealtro',
         '/uno/due/tre/',
         ]
print paths
print os.path.commonprefix(paths)
$ python ospath_commonprefix.py
['/uno/due/tre/quattro', '/uno/due/trequalchealtro', '/uno/due/tre/']
/uno/due/tre

Costruire Percorsi

A parte dividere percorsi esistenti, frequentemente occorre costruire percorsi da altre stringhe.

Per combinare diversi componenti di percorso in un singolo valore, si usa join():

import os.path

for parts in [ ('uno', 'due', 'tre'),
               ('/', 'uno', 'due', 'tre'),
               ('/uno', '/due', '/tre'),
               ]:
    print parts, ':', os.path.join(*parts)
$ python ospath_join.py
('uno', 'due', 'tre') : uno/due/tre
('/', 'uno', 'due', 'tre') : /uno/due/tre
('/uno', '/due', '/tre') : /tre

E' anche facile lavorare con percorsi che includono componenti inseriti in "variabili" che possono essere espanse automaticamente. Per esempio expanduser() converte il carattere tilde (~) nella directory home dell'utente.

import os.path

for user in [ '', 'dhellmann', 'postgres' ]:
    lookup = '~' + user
    print lookup, ':', os.path.expanduser(lookup)
$ python ospath_expanduser.py
~ : /Users/dhellmann
~dhellmann : /Users/dhellmann
~postgres : /var/empty

expandvars() è più generico, ed espande ogni variabile di ambiente della shell presente nel percorso

import os.path
import os

os.environ['LA_MIA_VARIABILE'] = 'VALORE'

print os.path.expandvars('/percorso/al/$LA_MIA_VARIABILE')
$ python ospath_expandvars.py
/percorso/al/VALORE

Normalizzare Percorsi

I percorsi assemblati da stringhe separate usando join() o con variabili incorporate potrebbero risultare con separatori extra o componenti di percorso relativo. L'uso di normpath() pulisce tutto:

import os.path

for path in [ 'uno//due//tre',
              'uno/./due/./tre',
              'uno/../uno/due/tre',
              ]:
    print path, ':', os.path.normpath(path)
$ python ospath_normpath.py
uno//due//tre : uno/due/tre
uno/./due/./tre : uno/due/tre
uno/../uno/due/tre : uno/due/tre

Per convertire un percorso relativo in un nome di file con percorso assoluto si usa abspath().

import os.path

for path in [ '.', '..', './uno/due/tre', '../uno/due/tre']:
    print '"%s" : "%s"' % (path, os.path.abspath(path))
$ python ospath_abspath.py
"." : "/Users/dhellmann/Documents/PyMOTW/src/PyMOTW/ospath"
".." : "/Users/dhellmann/Documents/PyMOTW/src/PyMOTW"
"./uno/due/tre" : "/Users/dhellmann/Documents/PyMOTW/src/PyMOTW/ospath/uno/due/tre"
"../uno/due/tre" : "/Users/dhellmann/Documents/PyMOTW/src/PyMOTW/uno/due/tre"

Data / Ora di File

A parte il lavoro con i percorsi, os.path include anche qualche funzione per recuperare le proprietà dei file, la qual cosa può essere molto più conveniente che chiamare os.stat():

import os.path
import time

print 'File           :', __file__
print 'Ultimo accesso :', time.ctime(os.path.getatime(__file__))
print 'Ultima modifica:', time.ctime(os.path.getmtime(__file__))
print 'Change time    :', time.ctime(os.path.getctime(__file__))
print 'Dimensione     :', os.path.getsize(__file__)
File           : ospath_properties.py
Ultimo accesso : Sat Jan 23 13:15:30 2010
Ultima modifica: Sat Jan 23 13:15:26 2010
Change time    : Sat Jan 23 13:15:26 2010
Dimensione     : 310

Verificare i File

Quando un programma trova un nome di percorso, spesso deve sapere se il percorso fa riferimento ad un file o ad una directory. Se si sta lavorando su di una piattaforma che lo supporta, si potrebbe avere bisogno di sapere se il percorso si riferisce ad un link simbolico o ad un punto di montaggio. Si potrebbe anche volere verificare se il percorso esiste o meno. os.path fornisce delle funzioni per verificare tutte queste condizioni.

import os.path

for file in [ __file__, os.path.dirname(__file__), '/', './link_non_valido']:
    print "File               :", file
    print "Assoluto           :", os.path.isabs(file)
    print "E' un file?        :", os.path.isfile(file)
    print "E' una directory?  :", os.path.isdir(file)
    print "E' un  Link?       :", os.path.islink(file)
    print "Punto di montaggio?:", os.path.ismount(file)
    print 'Esiste?            :', os.path.exists(file)
    print 'Esiste il Link?    :', os.path.lexists(file)
    print
$ ln -s /non/esiste link_non_valido
$ python ospath_tests.py
File               : ospath_tests.py
Assoluto           : False
E' un file?        : True
E' una directory?  : False
E' un  Link?       : False
Punto di montaggio?: False
Esiste?            : True
Esiste il Link?    : True

File               :
Assoluto           : False
E' un file?        : False
E' una directory?  : False
E' un  Link?       : False
Punto di montaggio?: False
Esiste?            : False
Esiste il Link?    : False

File               : /
Assoluto           : True
E' un file?        : False
E' una directory?  : True
E' un  Link?       : False
Punto di montaggio?: True
Esiste?            : True
Esiste il Link?    : True

File               : ./link_non_valido
Assoluto           : False
E' un file?        : False
E' una directory?  : False
E' un  Link?       : True
Punto di montaggio?: False
Esiste?            : False
Esiste il Link?    : True

Attraversare un albero di directory

os.path.walk() attraversa tutte le directory in un albero e chiama una funzione che viene fornita alla quale vengono passati il nome della directory ed i nomi del contenuto di quella directory. Questo esempio produce un elenco ricorsivo di directory, ignorando le directory svn.

import os
import os.path
import pprint

def visit(arg, dirname, names):
    print dirname, arg
    for name in names:
        subname = os.path.join(dirname, name)
        if os.path.isdir(subname):
            print '  %s/' % name
        else:
            print '  %s' % name
    print

os.mkdir('esempio')
os.mkdir('esempio/uno')
f = open('esempio/uno/file.txt', 'wt')
f.write('contenuto')
f.close()
f = open('esempio/due.txt', 'wt')
f.write('contenuto')
f.close()
os.path.walk('esempio', visit, '(Dati utente)')
$ python ospath_walk.py
esempio (Dati utente)
  uno/
  due.txt

esempio/uno (Dati utente)
  file.txt

Vedere anche:

os.path
La documentazione della libreria standard per questo modulo.
os
Il modulo os è il genitore di os.path.
Accesso ai File