How to read contents of 7z file using python
Asked Answered
P

7

40

How can I read and save the contents of 7z. I use Python 2.7.9, I can extract or Archive like this, but I can't read contents in python, I only listing the file's contents in CMD

import subprocess
import os

source = 'filename.7z'
directory = 'C:\Directory'
pw = '123456'
subprocess.call(r'"C:\Program Files (x86)\7-Zip\7z.exe" x '+source +' -o'+directory+' -p'+pw)
Predatory answered 26/9, 2015 at 13:45 Comment(1)
possible duplicate of Python - how to compress with 7zip instead of zip, code changingGoby
T
24

If you can use python 3, there is a useful library, py7zr, which supports 7zip archive compression, decompression, encryption and decryption.

import py7zr
with py7zr.SevenZipFile('sample.7z', mode='r') as z:
    z.extractall()
Transmissible answered 21/7, 2020 at 10:38 Comment(0)
B
7

I ended up in this situation where I was forced to use 7z, and also needed to know exactly which files were extracted from each zip archive. To deal with this, you can check the output of the call to 7z and look for the filenames. Here's what the output of 7z looks like:

$ 7z l sample.zip

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,8 CPUs x64)

Scanning the drive for archives:
1 file, 472 bytes (1 KiB)

Listing archive: sample.zip

--
Path = sample.zip
Type = zip
Physical Size = 472

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2018-12-01 17:09:59 .....            0            0  sample1.txt
2018-12-01 17:10:01 .....            0            0  sample2.txt
2018-12-01 17:10:03 .....            0            0  sample3.txt
------------------- ----- ------------ ------------  ------------------------
2018-12-01 17:10:03                  0            0  3 files

and how to parse that output with python:

import subprocess

def find_header(split_line):
    return 'Name' in split_line and 'Date' in split_line

def all_hyphens(line):
    return set(line) == set('-')

def parse_lines(lines):
    found_header = False
    found_first_hyphens = False
    files = []
    for line in lines:

        # After the header is a row of hyphens
        # and the data ends with a row of hyphens
        if found_header:
            is_hyphen = all_hyphens(''.join(line.split()))

            if not found_first_hyphens:
                found_first_hyphens = True
                # now the data starts
                continue

            # Finding a second row of hyphens means we're done
            if found_first_hyphens and is_hyphen:
                return files

        split_line = line.split()

        # Check for the column headers
        if find_header(split_line):
            found_header=True
            continue

        if found_header and found_first_hyphens:
            files.append(split_line[-1])
            continue

    raise ValueError("We parsed this zipfile without finding a second row of hyphens")



byte_result=subprocess.check_output('7z l sample.zip', shell=True)
str_result = byte_result.decode('utf-8')
line_result = str_result.splitlines()
files = parse_lines(line_result)
Bern answered 1/12, 2018 at 22:12 Comment(1)
Note this whole code can be reduced to [l.split()[-1] for l in str_result.rsplit("\n\n",1)[-1].splitlines()[2:-2]].Morita
O
5

You can use either libarchive-c or pylzma. If you can upgrade to python3.3+ you can use lzma, which is in the standard library.

EDIT 2024.01.01: Changed the link from libarchive to libarchive-c as the former is no longer in development and the new one works without much hassle with the libarchive library even on Windows.

Oasis answered 26/9, 2015 at 14:2 Comment(4)
I alway use python 2.7.9, I don't know 3.3+ has standard library for 7z, so thank you so muchPredatory
Note that lzma doesn’t work with 7z archives, only single files.Morita
So lzma is not the right library and I just wasted time to make it work. Downvote.Lechner
libarchive will not work on Windows by default. It will fail installing with this error: Library can not be loaded: Could not find module 'libarchive.so'.... You have to compile libarchive.dll yourself and add it - as well as several other .dlls it relies upon - to some folder recognized by your system PATH.Orthocephalic
N
3

you can Use pyunpack and patool library

!pip install pyunpack
!pip install patool
from pyunpack import Archive
Archive('7z file source').extractall('destination')

refer

https://pypi.org/project/patool/
https://pypi.org/project/pyunpack/

Niveous answered 6/11, 2019 at 5:26 Comment(0)
H
2

Here is how I get the list of all files in test.7z with Python:

from subprocess import Popen, PIPE
proc = Popen([r"C:\Program Files\7-Zip\7z.exe", "l", "-ba", "-slt", "test.7z"], stdout=PIPE)
files = [l.split('Path = ')[1] for l in proc.stdout.read().decode().splitlines() if l.startswith('Path = ')]

following the method from List zip file's contents using 7zip command line with non-verbose machine-friendly output.

This is a useful solution in the case you don't want to install another dependency package.

Haematogenesis answered 4/5, 2022 at 7:31 Comment(0)
M
1

Shelling out and calling 7z will extract files and then you can open() those files.

If you want to look inside a 7z archive directly within Python, then you'll need to use a library. Here's one: https://pypi.python.org/pypi/libarchive - I can't vouch for it as I said - I'm not a Python user - but using a 3rd party library is usually pretty easy in all languages.

Generally, 7z Support seems limited. If you can use alternative formats (zip/gzip) then I think you'll find the range of Python libraries (and example code) is more comprehensive.

Hope that helps.

Morey answered 26/9, 2015 at 13:56 Comment(1)
In practice using 7z is very useful via the subprocess module, you really have to test the 7zip command from the command line individually. and rely on the documentation to structure the command correctly. Once you understand how to form the 7z command line command, you are ready to build your subprocess command in Python.Aymer
T
0

Extract all the .7z files in a directory by doing this.

First, install

!pip install patool
!pip install pyunpack

And then

import os
from pyunpack import Archive

path = "path_to_file"
file_type = '.7z'

for filename in os.listdir(path=path):
    if filename.endswith(file_type):
        print(filename)
        print(f"{path}/{filename}")
        Archive(f"{path}/{filename}").extractall(f"{path}")```

Twohanded answered 7/5, 2022 at 11:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.