tarfile - Accesso ad Archivi Tar
Scopo: Accesso ad archivi Tar
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 tipo collegamenti fisici> e simbolici, nodi di dispositivo.
Verificare i File Tar
La funzione is_tarfile() restituisce un valore booleano che indica se il nome del file passato come argomento fa riferimento a un file tar valido.
# tarfile_is_tarfile.py
import tarfile
for filename in ['LEGGIMI.txt', 'esempio.tar',
'cattivo_esempio.tar', 'nonqui.tar']:
try:
print('{:>15} {}'.format(filename, tarfile.is_tarfile(
filename)))
except IOError as err:
print('{:>15} {}'.format(filename, err))
Se il file non esiste, is_tarfile() solleva una eccezione IOError.
$ python3 tarfile_is_tarfile.py
LEGGIMI.txt False
esempio.tar True
cattivo_esempio.tar False
nonqui.tar [Errno 2] No such file or directory: 'nonqui.tar'
Leggere Metadati da un File Tar
Per lavorare direttamente con un archivio tar si usi la classe TarFile. Essa supporta metodi per leggere dati su archivi esistenti così come per la modifica di archivi aggiungendo ulteriori file.
Per leggere i nomi dei file in un archivio esistente si usi getnames().
# tarfile_getnames.py
import tarfile
with tarfile.open('esempio.tar', 'r') as t:
print(t.getnames())
Il valore di ritorno è una lista di stringhe con i nomi del contenuto dell'archivio.
$ python3 tarfile_getnames.py ['LEGGIMI.txt']
Oltre ai nomi, i metadati circa i membri dell'archivio sono disponibili come istanze di oggetti Tarinfo. I meta-dati si caricano tramite getmembers() e getmember().
# tarfile_getmembers.py
import tarfile
import time
with tarfile.open('esempio.tar', 'r') as t:
for member_info in t.getmembers():
print(member_info.name)
print(' Modificato:', time.ctime(member_info.mtime))
print(' Modalità :', oct(member_info.mode))
print(' Tipo :', member_info.type)
print(' Dimensione:', member_info.size, 'byte')
print()
$ python3 tarfile_getmembers.py LEGGIMI.txt Modificato: Tue Mar 16 21:15:58 2010 Modalità : 0o644 Tipo : b'0' Dimensione: 77 byte
Se si conosce in anticipo il nome del membro dell'archivio si può ottenere il suo oggetto Tarinfo con getmember().
# tarfile_getmember.py
import tarfile
import time
with tarfile.open('esempio.tar', 'r') as t:
for filename in [ 'LEGGIMI.txt', 'nonqui.txt' ]:
try:
info = t.getmember(filename)
except KeyError:
print("ERROE: {} non trovato nell'archivio tar".format(
filename))
else:
print("{} è {:d} byte".format(
info.name, info.size))
Se il membro dell'archivio non è presente, getmember() solleva una eccezione KeyError.
$ python3 tarfile_getmember.py LEGGIMI.txt è 77 byte ERROE: nonqui.txt non trovato nell'archivio tar
Estrarre File da un Archivio
Per accedere ai dati da un membro di un archivio all'interno di un programma, si usi il metodo extractfile(), passandogli il nome del membro.
# tarfile_extractfile.py
import tarfile
with tarfile.open('esempio.tar', 'r') as t:
for filename in [ 'LEGGIMI.txt', 'nonqui.txt' ]:
try:
f = t.extractfile(filename)
except KeyError:
print("ERROR: {} non trovato nell'archivio tar".format(
filename))
else:
print(filename, ':')
print(f.read().decode('utf-8'))
Il valore ritornato è un oggetto tipo file dal quale è possibile leggere il contenuto del membro dell'archivio.
$ python3 tarfile_extractfile.py LEGGIMI.txt : Gli esempi per il modulo tarfile usano questo file ed esempio.tar come dati. ERROR: nonqui.txt non trovato nell'archivio tar
Se si vuole estrarre il contenuto dell'archivio e scrivere i file nel filesystem, si usino extract() oppure extractall().
# tarfile_extract.py
import tarfile
import os
os.mkdir('outdir')
with tarfile.open('esempio.tar', 'r') as t:
t.extract('LEGGIMI.txt', 'outdir')
print(os.listdir('outdir'))
Il membro o i membri sono letti dall'archivio e scritti al filesystem, a partire dalla directory specificata negli argomenti.
$ python3 tarfile_extract.py
Traceback (most recent call last):
File "tarfile_extract.py", line 6, in <module>
os.mkdir('outdir')
FileExistsError: [Errno 17] File exists: 'outdir'
La documentazione della libreria standard include una nota che afferma che extractall() è più sicuro di extract(), specialmente lavorando con dati che si stanno ricevendo da un flusso dove rileggere una parte precedente dell'input non è possibile, quindi dovrebbe essere usato nella maggior parte dei casi.
# tarfile_extractall.py
import tarfile
import os
os.mkdir('outdir')
with tarfile.open('esempio.tar', 'r') as t:
t.extractall('outdir')
print(os.listdir('outdir'))
Con extractall(), il primo argomento è il nome della directory dove i file dovrebbero essere scritti.
$ python3 tarfile_extractall.py ['LEGGIMI.txt']
Per estrarre specifici file dall'archivio, si passino i loro nomi o dei contenitori di metadati TarInfo ad extractall().
# tarfile_extractall_members.py
import tarfile
import os
os.mkdir('outdir')
with tarfile.open('esempio.tar', 'r') as t:
t.extractall('outdir',
members=[t.getmember('LEGGIMI.txt')],
)
print(os.listdir('outdir'))
Quando viene passato un elenco di membri, vengono estratti solo i file inclusi nella lista.
$ python3 tarfile_extractall_members.py ['LEGGIMI.txt']
Creare Nuovi Archivi
Per creare un nuovo archivio, si apra un file tar con TarFile in modalità 'w'.
# tarfile_add.py
import tarfile
print('creazione archivio')
with tarfile.open('tarfile_aggiunto.tar', mode='w') as out:
print('aggiunto LEGGIMI.txt')
out.add('LEGGIMI.txt')
print()
print('Contenuto:')
with tarfile.open('tarfile_aggiunto.tar', mode='r') as t:
for member_info in t.getmembers():
print(member_info.name)
Un qualsiasi file esistente viene troncato e viene inizializzato un nuovo archivio. Per aggiungere dei file si usi il metodo add().
$ python3 tarfile_add.py creazione archivio aggiunto LEGGIMI.txt Contenuto: LEGGIMI.txt
Usare Nomi Alternativi per i Membri di un Archivio
E' possibile aggiungere un file a 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().
# tarfile_addfile.py
import tarfile
print('creazione archivio')
with tarfile.open('tarfile_aggiuntofile.tar', mode='w') as out:
print('aggiunto LEGGIMI.txt come RINOMINATO.txt')
info = out.gettarinfo('LEGGIMI.txt', arcname='RINOMINATO.txt')
out.addfile(info)
print()
print('Contenuto:')
with tarfile.open('tarfile_aggiuntofile.tar', mode='r') as t:
for member_info in t.getmembers():
print(member_info.name)
L'archivio comprende solo il file con il nome cambiato.
$ python3 tarfile_addfile.py creazione archivio aggiunto LEGGIMI.txt come RINOMINATO.txt Contenuto: RINOMINATO.txt
Scrivere Dati da Sorgenti Diverse Dai File
Talvolta è necessario scrivere dati in un archivio direttamente dalla memoria. Invece che scrivere dati a un file, quindi aggiungere quel file all'archivio, si può usare addfile() per aggiungere dati da un handle di tipo file aperto che ritorni byte.
tarfile_aggiungifile_stringa.tar
Per prima cosa si costruisca un oggetto Tarinfo, si può assegnare al membro dell'archivio un qualsiasi nome a scelta. Dopo averne impostata la dimensione, i dati vengono scritti nell'archivio usando addfile(), e passando un buffer BytesIO come sorgente dei dati.
$ python3 tarfile_addfile_string.py Contenuto: file_inventato.txt Questi sono i dati da scrivere nell'archivio.
Aggiungere agli Archivi
Oltre alla creazione di nuovi archivi, è possibile aggiungere dati a un file esistente usando la modalità 'a'.
# tarfile_append.py
import tarfile
print('creazione archivio')
with tarfile.open('tarfile_accoda.tar', mode='w') as out:
out.add('LEGGIMI.txt')
print('contenuto:',)
with tarfile.open('tarfile_accoda.tar', mode='r') as t:
print([m.name for m in t.getmembers()])
print('si accoda index.rst')
with tarfile.open('tarfile_accoda.tar', mode='a') as out:
out.add('index.rst')
print('contenuto:',)
with tarfile.open('tarfile_accoda.tar', mode='r') as t:
print([m.name for m in t.getmembers()])
L'archivio che ne deriva conterrà due membri.
$ python3 tarfile_append.py creazione archivio contenuto: ['LEGGIMI.txt'] si accoda index.rst contenuto: ['LEGGIMI.txt', 'index.rst']
Lavorare con Archivi Compressi
Oltre ai normali archivi tar, il modulo tarfile può lavorare anche con archivi compressi tramite i protocolli gzip o bzip2. Per aprire un archivio compresso, si modifichi la stringa della modalità passata ad open() per includere ":gz" oppure :bz2, a seconda del metodo di compressione desiderato.
# tarfile_compression.py
import tarfile
import os
fmt = '{:<30} {:<10}'
print(fmt.format('NOME FILE', 'DIMENSIONE'))
print(fmt.format('LEGGIMI.txt', os.stat('LEGGIMI.txt').st_size))
FILES = [
('tarfile_compressione.tar', 'w'),
('tarfile_compressione.tar.gz', 'w:gz'),
('tarfile_compressione.tar.bz2', 'w:bz2'),
]
for filename, write_mode in FILES:
with tarfile.open(filename, mode=write_mode) as out:
out.add('LEGGIMI.txt')
print(fmt.format(filename, os.stat(filename).st_size),
end=' ')
print([
m.name
for m in tarfile.open(filename, 'r:*').getmembers()
])
Quando si apre un archivio esistente in lettura, si specifichi "r:*" affinchè tarfile possa determinare il metodo di compressione da usare automaticamente.
$ python3 tarfile_compression.py NOME FILE DIMENSIONE LEGGIMI.txt 61 tarfile_compressione.tar 10240 ['LEGGIMI.txt'] tarfile_compressione.tar.gz 255 ['LEGGIMI.txt'] tarfile_compressione.tar.bz2 238 ['LEGGIMI.txt']
Vedere anche:
- tarfile
- La documentazione della libreria standard per questo modulo.
- GNU tar manual
- Documentazione del formato tar, incluse le estensioni.
- zipfile
- Accesso similare agli archivi ZIP
- gzip
- Compressione GNU zip
- bz2
- Compressione bz2