change the content of zip object by adding blank line at the end

Question:

I am opening a zip file using python like this…

with open('/home/ubuntu/myzip/myzip.zip', 'rb') as zf:

It is working as expected. The contents zf.read() are passed to an API. Is there any way to modify the file without chaging it’s content? For e.g. adding an enter mark at the end.

I need to do this so that the service should consider it as a different file. It is not accepting the same content for some reason.

Asked By: shantanuo

||

Answers:

Opening ZIP Files for Reading and Writing

import zipfile

>>> with zipfile.ZipFile("sample.zip", 
mode="r") as archive:
...     archive.printdir()
...
File Name                                        
Modified             Size
hello.txt                                 
2021-09-07 19:50:10           83
lorem.md                                  
2021-09-07 19:50:10         2609
realpython.md                             
2021-09-07 19:50:10          428

The first argument to the initializer of ZipFile can be a string representing the path to the ZIP file that you need to open. This argument can accept file-like and path-like objects too. In this example, you use a string-based path.

The second argument to ZipFile is a single-letter string representing the mode that you’ll use to open the file. As you learned at the beginning of this section, ZipFile can accept four possible modes, depending on your needs. The mode positional argument defaults to "r", so you can get rid of it if you want to open the archive for reading only.

Inside the with statement, you call .printdir() on archive. The archive variable now holds the instance of ZipFile itself. This function provides a quick way to display the content of the underlying ZIP file on your screen. The function’s output has a user-friendly tabular format with three informative columns:

File Name
Modified
Size
If you want to make sure that you’re targeting a valid ZIP file before you try to open it, then you can wrap ZipFile in a try … except statement and catch any BadZipFile exception:

>>> import zipfile

>>> try:
...     with zipfile.ZipFile("sample.zip") as 
archive:
...         archive.printdir()
... except zipfile.BadZipFile as error:
...     print(error)
...
File Name                                        
Modified             Size
hello.txt                                 
2021-09-07 19:50:10           83
lorem.md                                  
2021-09-07 19:50:10         2609
realpython.md                             
2021-09-07 19:50:10          428

>>> try:
...     with 
zipfile.ZipFile("bad_sample.zip") as archive:
...         archive.printdir()
... except zipfile.BadZipFile as error:
...     print(error)
...
File is not a zip file

The first example successfully opens sample.zip without raising a BadZipFile exception. That’s because sample.zip has a valid ZIP format. On the other hand, the second example doesn’t succeed in opening bad_sample.zip, because the file is not a valid ZIP file.

To check for a valid ZIP file, you can also use the is_zipfile() function:

>>> import zipfile

>>> if zipfile.is_zipfile("sample.zip"):
...     with zipfile.ZipFile("sample.zip", 
"r") as archive:
...         archive.printdir()
... else:
...     print("File is not a zip file")
...
File Name                                        
Modified             Size
hello.txt                                 
2021-09-07 19:50:10           83
lorem.md                                  
2021-09-07 19:50:10         2609
realpython.md                             
2021-09-07 19:50:10          428

>>> if zipfile.is_zipfile("bad_sample.zip"):
...     with 
zipfile.ZipFile("bad_sample.zip", "r") as 
archive:
...         archive.printdir()
... else:
...     print("File is not a zip file")
...
File is not a zip file

In these examples, you use a conditional statement with is_zipfile() as a condition. This function takes a filename argument that holds the path to a ZIP file in your file system. This argument can accept string, file-like, or path-like objects. The function returns True if filename is a valid ZIP file. Otherwise, it returns False.

Now say you want to add hello.txt to a hello.zip archive using ZipFile. To do that, you can use the write mode ("w"). This mode opens a ZIP file for writing. If the target ZIP file exists, then the "w" mode truncates it and writes any new content you pass in.

Note: If you’re using ZipFile with existing files, then you should be careful with the "w" mode. You can truncate your ZIP file and lose all the original content.

If the target ZIP file doesn’t exist, then ZipFile creates it for you when you close the archive:

>>> import zipfile

>>> with zipfile.ZipFile("hello.zip", 
mode="w") as archive:
...     archive.write("hello.txt")
...

After running this code, you’ll have a hello.zip file in your python-zipfile/ directory. If you list the file content using .printdir(), then you’ll notice that hello.txt will be there. In this example, you call .write() on the ZipFile object. This method allows you to write member files into your ZIP archives. Note that the argument to .write() should be an existing file.

Note: ZipFile is smart enough to create a new archive when you use the class in writing mode and the target archive doesn’t exist. However, the class doesn’t create new directories in the path to the target ZIP file if those directories don’t already exist.

That explains why the following code won’t work:

>>> import zipfile

>>> with zipfile.ZipFile("missing/hello.zip", 
mode="w") as archive:
...     archive.write("hello.txt")
...
Traceback (most recent call last):
...
FileNotFoundError: [Errno 2] No such file or 
directory: 'missing/hello.zip'

Because the missing/ directory in the path to the target hello.zip file doesn’t exist, you get a FileNotFoundError exception.

The append mode ("a") allows you to append new member files to an existing ZIP file. This mode doesn’t truncate the archive, so its original content is safe. If the target ZIP file doesn’t exist, then the "a" mode creates a new one for you and then appends any input files that you pass as an argument to .write().

To try out the "a" mode, go ahead and add the new_hello.txt file to your newly created hello.zip archive:

>>> import zipfile

>>> with zipfile.ZipFile("hello.zip", 
mode="a") as archive:
...     archive.write("new_hello.txt")
...

>>> with zipfile.ZipFile("hello.zip") as 
archive:
...     archive.printdir()
...
File Name                                        
Modified             Size
hello.txt                                 
2021-09-07 19:50:10           83
new_hello.txt                             
2021-08-31 17:13:44  

Here, you use the append mode to add new_hello.txt to the hello.zip file. Then you run .printdir() to confirm that the new file is present in the ZIP file.

ZipFile also supports an exclusive mode ("x"). This mode allows you to exclusively create new ZIP files and write new member files into them. You’ll use the exclusive mode when you want to make a new ZIP file without overwriting an existing one. If the target file already exists, then you get FileExistsError.

Finally, if you create a ZIP file using the "w", "a", or "x" mode and then close the archive without adding any member files, then ZipFile creates an empty archive with the appropriate ZIP format.

Answered By: D P
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.