41

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) 
1

7 Answers 7

27

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() 
Sign up to request clarification or add additional context in comments.

Comments

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) 

1 Comment

Note this whole code can be reduced to [l.split()[-1] for l in str_result.rsplit("\n\n",1)[-1].splitlines()[2:-2]].
4

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.

4 Comments

I alway use python 2.7.9, I don't know 3.3+ has standard library for 7z, so thank you so much
Note that lzma doesn’t work with 7z archives, only single files.
So lzma is not the right library and I just wasted time to make it work. Downvote.
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.
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/

Comments

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.

Comments

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.

1 Comment

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.
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}")``` 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.