¿Cómo saber si un archivo está comprimido con gzip?

Tengo un progtwig en Python que tomará archivos de texto como entrada. Sin embargo, algunos de estos archivos pueden estar comprimidos con gzip.

¿Existe una plataforma multiplataforma, utilizable desde Python para determinar si un archivo está comprimido con gzip o no?

¿Es lo siguiente confiable o podría un archivo de texto normal ‘accidentalmente’ tener el mismo aspecto que gzip para que obtenga falsos positivos?

try: gzip.GzipFile(filename, 'r') # compressed # ... except: # not compressed # ... 

    El número mágico para archivos comprimidos con gzip es 1f 8b . Aunque probar esto no es 100% confiable, es altamente improbable que los “archivos de texto ordinarios” comiencen con esos dos bytes, en UTF-8 ni siquiera es legal.

    Por lo general, los archivos comprimidos con gzip tienen el sufijo .gz . Incluso gzip(1) no desempaquetará los archivos sin él a menos que usted lo --force hacerlo. Posiblemente podría usar eso, pero todavía tendría que lidiar con un posible error IOE (que en cualquier caso debe hacerlo).

    Un problema con su enfoque es que gzip.GzipFile() no lanzará una excepción si lo alimenta con un archivo sin comprimir. Sólo una read() posterior read() hará. Esto significa que probablemente tendría que implementar parte de la lógica de su progtwig dos veces. Feo.

    “¿Existe una plataforma multiplataforma, utilizable desde Python para determinar si un archivo está comprimido con gzip o no?”

    La respuesta aceptada me dio el 90% de la solución bastante confiable (compruebe si los dos primeros bytes son 1f 8b ), pero no mostró cómo hacer esto en Python. Aquí hay una manera posible:

     import binascii def is_gz_file(filepath): with open(filepath, 'rb') as test_f: return binascii.hexlify(test_f.read(2)) == b'1f8b' 

    Importar el módulo mimetypes . Puede adivinar automáticamente qué tipo de archivo tiene, y si está comprimido.

    es decir

     mimetypes.guess_type('blabla.txt.gz') 

    devoluciones:

    (‘text / plain’, ‘gzip’)

    gzip generará un OSError si no es un archivo comprimido.

     >>> with gzip.open('README.md', 'rb') as f: ... f.read() ... Traceback (most recent call last): File "", line 2, in  File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 276, in read return self._buffer.read(size) File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 463, in read if not self._read_gzip_header(): File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 411, in _read_gzip_header raise OSError('Not a gzipped file (%r)' % magic) OSError: Not a gzipped file (b'# ') 

    Puede combinar este enfoque con otros para boost la confianza, como verificar el tipo MIME o buscar un número mágico en el encabezado del archivo (ver otras respuestas para ver un ejemplo) y verificar la extensión.

     import pathlib if '.gz' in pathlib.Path(filepath).suffixes: # some more inexpensive checks until confident we can attempt to decompress # ... try ... ... except OSError as e: ... 

    Parece que no funciona bien en python3 …

     import mimetypes filename = "./datasets/test" def file_type(filename): type = mimetypes.guess_type(filename) return type print(file_type(filename)) 

    devuelve (Ninguno, Ninguno) Pero desde el comando “Archivo” de Unix

    : ~> archivo de datos / prueba de datos / prueba: datos comprimidos de gzip, fue “iostat_collection”, de Unix, última modificación: jue 29 de enero 07:09:34 2015