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