Scopo | Accesso ad archivi Tar |
Versione Python | 2.3 e successive |
A partire dal 1 gennaio 2021 le versioni 2.x di Python non sono piu' supportate. Ti invito a consultare la corrispondente versione 3.x dell'articolo per il modulo tarfile
Il modulo tarfile fornisce accesso in lettura e scrittura agli archivi UNIX tar, inclusi i file compressi. Oltre agli standard POSIX parecchie estensioni GNU tar sono supportate. Sono gestiti anche diversi tipi di file speciale UNIX (link hard e soft, nodi di dispositivo ecc.).
La funzione
is_tarfile()
restituisce un valore booleano che indica se il nome del file passato come parametro fa riferimento ad un file tar valido.
import tarfile
for filename in [ 'LEGGIMI.txt', 'esempio.tar',
'cattivo_esempio.tar', 'nonqui.tar' ]:
try:
print '%20s %s' % (filename, tarfile.is_tarfile(filename))
except IOError, err:
print '%20s %s' % (filename, err)
Si noti che se il file non esiste, is_tarfile() solleva un IOError.
$ python tarfile_is_tarfile.py LEGGIMI.txt True esempio.tar True cattivo_esempio.tar False nonqui.tar [Errno 2] No such file or directory: 'nonqui.tar'
Per lavorare direttamente con un archivio tar si usa la classe TarFile . Essa supporta metodi per leggere dati su archivi esistenti così come la modifica di archivi aggiungendo ulteriori file.
Per leggere i nomi dei file in un archivio esistente si usa
getnames()
.
import tarfile
t = tarfile.open('esempio.tar', 'r')
print t.getnames()
Il valore di ritorno è una lista di stringhe con i nomi del contenuto dell'archivio.
$ python tarfile_getnames.py ['LEGGIMI.txt']
Oltre ai nomi, i meta-dati circa i membri dell'archivio sono disponibili come istanze di oggetti
Tarinfo
. I meta-dati si caricano tramite
getmembers()
e
getmember()
.
import tarfile
import time
t = tarfile.open('esempio.tar', 'r')
for member_info in t.getmembers():
print member_info.name
print '\tModificato:\t', time.ctime(member_info.mtime)
print '\tModalità :\t', oct(member_info.mode)
print '\tTipo :\t', member_info.type
print '\tDimensione:\t', member_info.size, 'bytes'
print
$ python tarfile_getmembers.py LEGGIMI.txt Modificato: Tue Mar 16 20:33:22 2010 Modalità : 0644 Tipo : 0 Dimensione: 31 bytes
Se si conosce in anticipo il nome del membro dell'archivio si può ottenere il suo oggetto Tarinfo con getmember().
import tarfile
import time
t = tarfile.open('esempio.tar', 'r')
for filename in [ 'LEGGIMI.txt', 'nonqui.txt' ]:
try:
info = t.getmember(filename)
except KeyError:
print "ERRORE: Non trovato %s nell'archivio tar" % filename
else:
print '%s è di %d bytes' % (info.name, info.size)
Se il membro dell'archivio non è presente, getmember() solleva un KeyError.
$ python tarfile_getmember.py LEGGIMI.txt è di 31 bytes ERRORE: Non trovato nonqui.txt nell'archivio tar
Per accedere ai dati da un membro di un archivio all'interno del proprio programma, si usa il metodo
extractfile()
, passandogli il nome del membro.
import tarfile
t = tarfile.open('esempio.tar', 'r')
for filename in [ 'LEGGIMI.txt', 'nonqui.txt' ]:
try:
f = t.extractfile(filename)
except KeyError:
print "ERRORE: Non trovato %s nell'archivio tar" % filename
else:
print filename, ':', f.read()
$ python tarfile_extractfile.py LEGGIMI.txt : Gli esempi per il modulo tarfile usano questo file ed esempio.tar come dati. ERRORE: Non trovato nonqui.txt nell'archivio tar
Se si vuole semplicemente spacchettare l'archivio e scrivere i file nel filesystem, si usano invece
extract()
oppure
extractall()
.
import tarfile
import os
os.mkdir('outdir')
t = tarfile.open('esempio.tar', 'r')
t.extract('LEGGIMI.txt', 'outdir')
print os.listdir('outdir')
$ python tarfile_extractall.py ['LEGGIMI.txt']
import tarfile
import os
os.mkdir('outdir')
t = tarfile.open('esempio.tar', 'r')
t.extractall('outdir')
print os.listdir('outdir')
Se si vuole estrarre solo alcuni file dall'archivio, i loro nomi possono essere passati a extractall().
import tarfile
import os
os.mkdir('outdir')
t = tarfile.open('esempio.tar', 'r')
t.extractall('outdir', members=[t.getmember('LEGGIMI.txt')])
print os.listdir('outdir')
$ python tarfile_extractall.py ['LEGGIMI.txt']
Per creare un nuovo archivio, si apre semplicemente TarFile in modalità
'w'
. Un qualsiasi file esistente viene troncato e viene creato un nuovo archivio. Per aggiungere dei file si usa il metodo
add()
.
import tarfile
print 'creazione archivio'
out = tarfile.open('tarfile_aggiunto.tar', mode='w')
try:
print 'aggiunta di LEGGIMI.txt'
out.add('LEGGIMI.txt')
finally:
print 'chiusura'
out.close()
print
print 'Contenuto:'
t = tarfile.open('tarfile_aggiunto.tar', 'r')
for member_info in t.getmembers():
print member_info.name
$ python tarfile_add.py creazione archivio aggiunta di LEGGIMI.txt chiusura Contenuto: LEGGIMI.txt
E' possibile aggiungere un file ad un archivio usando un nome diverso da quello del file originale, costruendo un oggetto Tarinfo con un nome alternativo assegnato al parametro
arcname
che viene quindi passato ad
addfile()
.
import tarfile
print 'creazione archivio'
out = tarfile.open('tarfile_aggiungifile.tar', mode='w')
try:
print 'aggiunto LEGGIMI.txt come RINOMINATO.txt'
info = out.gettarinfo('LEGGIMI.txt', arcname='RINOMINATO.txt')
out.addfile(info)
finally:
print 'chiusura'
out.close()
print
print 'Contenuto:'
t = tarfile.open('tarfile_aggiungifile.tar', 'r')
for member_info in t.getmembers():
print member_info.name
L'archivio comprende solo il file con il nome cambiato.
$ python tarfile_addfile.py creazione archivio aggiunto LEGGIMI.txt come RINOMINATO.txt chiusura Contenuto: RINOMINATO.txt
Talvolta si vuole scrivere dati ad un archivio, ma gli stessi non sono rappresentati da un file nel filesystem. Invece che scrivere dei dati ad un file, quindi aggiungere quel file all'archivio, si può usare
addfile()
per aggiungere dati da un handle di file aperto.
import tarfile
from cStringIO import StringIO
data = "Questi sono i dati da scrivere nell'archivio."
out = tarfile.open('tarfile_aggiungifile_stringa.tar', mode='w')
try:
info = tarfile.TarInfo('made_up_file.txt')
info.size = len(data)
out.addfile(info, StringIO(data))
finally:
out.close()
print
print 'Contenuto:'
t = tarfile.open('tarfile_aggiungifile_stringa.tar', 'r')
for member_info in t.getmembers():
print member_info.name
f = t.extractfile(member_info)
print f.read()
Se si costruisce autonomamente un oggetto Tarinfo, si può assegnare al membro dell'archivio un qualsiasi nome a scelta. Dopo averne impostata la dimensione, si possono scrivere i dati nell'archivio usando addfile(), e passando un buffer StringIO come sorgente dei dati.
$ python tarfile_addfile_string.py Contenuto: made_up_file.txt Questi sono i dati da scrivere nell'archivio.
Oltre alla creazione di nuovi archivi, è possibile aggiungere dati ad un archivio esistente. Per farlo si apre il file usando la modalità
'a'
.
import tarfile
print 'creazione archivio'
out = tarfile.open('tarfile_accoda.tar', mode='w')
try:
out.add('LEGGIMI.txt')
finally:
out.close()
print 'contenuto:', [m.name
for m in tarfile.open('tarfile_accoda.tar', 'r').getmembers()]
print 'accodo index.rst'
out = tarfile.open('tarfile_accoda.tar', mode='a')
try:
out.add('index.rst')
finally:
out.close()
print 'contenuto:', [m.name
for m in tarfile.open('tarfile_accoda.tar', 'r').getmembers()]
L'archivio che ne deriva conterrà due membri.
$ python tarfile_append.py creazione archivio contenuto: ['LEGGIMI.txt'] accodo index.rst contenuto: ['LEGGIMI.txt', 'index.rst']
Oltre ai normali archivi tar, il modulo tarfile può lavorare anche con archivi compressi tramite i protocolli gzip e bzip2. Per aprire un archivio compresso, si modifica la stringa della modalità passata ad open() per includere
":gzip"
oppure
:bz2
, a seconda del metodo di compressione che si intende usare.
import tarfile
import os
fmt = '%-30s %-10s'
print fmt % ('NOME FILE', 'DIMENSIONE')
print fmt % ('LEGGIMI.txt', os.stat('LEGGIMI.txt').st_size)
for filename, write_mode in [
('tarfile_compressione.tar', 'w'),
('tarfile_compressione.tar.gz', 'w:gz'),
('tarfile_compressione.tar.bz2', 'w:bz2'),
]:
out = tarfile.open(filename, mode=write_mode)
try:
out.add('LEGGIMI.txt')
finally:
out.close()
print fmt % (filename, os.stat(filename).st_size),
print [m.name for m in tarfile.open(filename, 'r:*').getmembers()]
Quando si apre un archivio esistente in lettura, si può specificare
"r:*"
affinchè tarfile possa determinare il metodo di compressione da usare automaticamente.
$ python tarfile_compression.py NOME FILE DIMENSIONE LEGGIMI.txt 77 tarfile_compressione.tar 10240 ['LEGGIMI.txt'] tarfile_compressione.tar.gz 210 ['LEGGIMI.txt'] tarfile_compressione.tar.bz2 194 ['LEGGIMI.txt']
Vedere anche: