Exercise 1 solution import gzip import os import tempfile import zipfile SIGNATURES = [ (b"\x89PNG\r\n\x1a\n", "PNG image"), (b"\xff\xd8\xff", "JPEG image"), (b"GIF87a", "GIF image"), (b"GIF89a", "GIF image"), (b"%PDF-", "PDF document"), (b"PK\x03\x04", "ZIP archive"), (b"\x1f\x8b", "gzip data"), ] def identify_file(path): with open(path, "rb") as f: head = f.read(16) if not head: return "empty file" for magic, name in SIGNATURES: if head.startswith(magic): return name return "unknown" with tempfile.TemporaryDirectory() as folder: def make(name, data): path = os.path.join(folder, name) with open(path, "wb") as f: f.write(data) return path paths = [ make("a.png", b"\x89PNG\r\n\x1a\n" + bytes(8)), make("b.pdf", b"%PDF-1.4\n"), make("c.gif", b"GIF89a" + bytes(10)), make("d.dat", b"hello, plain text"), make("e.png", b"not really a png"), make("f.bin", b""), ] zpath = os.path.join(folder, "g.zip") with zipfile.ZipFile(zpath, "w") as z: z.writestr("x.txt", "hi") paths.append(zpath) gpath = os.path.join(folder, "h.gz") with gzip.open(gpath, "wb") as g: g.write(b"hi") paths.append(gpath) for p in paths: print(os.path.basename(p), "->", identify_file(p)) print(os.path.exists(folder)) # a.png -> PNG image # b.pdf -> PDF document # c.gif -> GIF image # d.dat -> unknown # e.png -> unknown # f.bin -> empty file # g.zip -> ZIP archive # h.gz -> gzip data # False (Run as written; the output matched the comments.) Explanation: a file's name is only a label, so the function trusts the first bytes instead. It reads at most 16 bytes, which is enough for every signature in the table, returns "empty file" before trying any match, and falls back to "unknown" for anything else. The plain-text file called e.png is not reported as a PNG, because its content does not start with the PNG signature. The ZIP and gzip files were produced by the standard zipfile and gzip modules, so the signatures matched real output.