Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

The right way to use zipimport; "zipimport.ZipImportError: not a Zip file" on a seemingly valid file

Ask Question

I have managed to use this module without installation - just import it from path to use ,

import sys 
url = 'https://example.com' 
sys.path.insert(0, r'C:\Users\i\Downloads\you-get-0.4.1128\src')  # 
from you_get import common 
common.any_download(url, info_only=True)#NoneType 

It seems possible in Python to use zipimport to directly use the zip archive of the module without extraction, I wonder what is the right way to use zipimport, a simple trying like the following just gives the exception . I downloaded the file from here , the file C:\Users\i\Downloads\you-get-0.4.1128.zip does exist and isn't corrupted.

>>> import zipimport 
>>> zipimport.zipimporter(r'C:\Users\i\Downloads\you-get-0.4.1128.zip') 
Traceback (most recent call last): 
  File "<pyshell#1>", line 1, in <module> 
    zipimport.zipimporter(r'C:\Users\i\Downloads\you-get-0.4.1128.zip') 
zipimport.ZipImportError: not a Zip file: 'C:\\Users\\i\\Downloads\\you-get-0.4.1128.zip' 
                @ivan_pozdeev I downloaded the file from github.com/soimort/you-get/archive/v0.4.1128.zip
– iMath
                Aug 13, 2018 at 10:57

(This is the suggested way of action that answers your question: "The right way to use zipimport"; see further below for the immediate cause of your error.)

You shouldn't use zipimport directly. Instead, you should add the .zip file to sys.path -- it will be used as if it was a directory.

That said, the file you downloaded is a source distribution -- it has a setup.py in root and the actual modules in a subdirectory. To use the module, you need a built distribution instead.

Telling all about source and built distributions is beyond the scope of a single answer. One possible way to go is to:

  • unpack the .zip
  • make a wheel using its setup.py with python setup.py bdist_wheel and
  • install it with pip install <path to .whl>
  • Debugging with Visual Studio shows that this is the code that it chokes on:

    v3.6.5,Modules\zipimport.c:

    if (fseek(fp, -22, SEEK_END) == -1) {
    header_position = (unsigned long)ftell(fp);
    if (fread(buffer, 1, 22, fp) != 22) {
    if (get_uint32(buffer) != 0x06054B50u) {
        /* Bad: End of Central Dir signature */
        errmsg = "not a Zip file";
        goto invalid_header;
    

    As you can see, it reads and validates the last 22 bytes of the file as an "end of central dir signature".

    The spec says:

    4.3.1 A ZIP file MUST contain an "end of central directory record".

    4.3.6 Overall .ZIP file format:

    [end of central directory record]

    4.3.16 End of central directory record:

      end of central dir signature    4 bytes  (0x06054b50)
      number of this disk             2 bytes
      number of the disk with the
      start of the central directory  2 bytes
      total number of entries in the
      central directory on this disk  2 bytes
      total number of entries in
      the central directory           2 bytes
      size of the central directory   4 bytes
      offset of start of central
      directory with respect to
      the starting disk number        4 bytes
      .ZIP file comment length        2 bytes
      .ZIP file comment       (variable size)
    

    As you can see, this "End of central directory record" is 22 bytes.. without the comment. And this file does have a comment:

    $ xxd -s 0x322b5 -g 1 you-get-0.4.1128.zip
    000322b5: 50 4b 05 06 00 00 00 00 af 00 af 00 25 45 00 00  PK..........%E..
    000322c5: 90 dd 02 00 28 00 61 30 62 39 37 65 35 36 65 35  ....(.a0b97e56e5
    000322d5: 36 35 38 36 33 35 62 35 63 35 66 32 66 33 32 65  658635b5c5f2f32e
    000322e5: 38 62 38 63 31 34 62 64 33 35 61 65 62 33        8b8c14bd35aeb3
    

    So this is a bug. Here's a relevant ticket.

    Thanks to your explanation , I extract the zip archive and then add the extracted to a zip archive using Bandizip, this time zipimport.zipimporter(r'C:\Users\i\Downloads\you-get-0.4.1128.zip') doesn't give the exception , but still cannot import the module, even adding the .zip file to sys.path, tested code here bpaste.net/show/243292a2d4a6 – iMath Aug 14, 2018 at 7:15 @iMath See the text after "That said...". You need to either make a built distribution from that archive or download and install the .whl from the same site instead. Unless you have some special needs, this is the standard approach to 3rd-party packages. – ivan_pozdeev Aug 14, 2018 at 7:21 What I actually want to do is to use the module from a pyinstaller frozen application , I also need to upgrade the module to latest version whenever needed , I cannot find a solution yet. – iMath Aug 14, 2018 at 7:22 @iMath Ask a separate question about that, accurately and in detail describing your use scenarios (=what you have and what you're trying to achieve). The information you gave is not enough to get the full picture, and it sounds like a large enough matter for another full question and answer. Finally, it's a completely separate matter (organizing your modules for some use scenario) from what you asked here (a problem importing from a specific .zip file), and SO is one-concern-per-question to stay useful for future readers. – ivan_pozdeev Aug 14, 2018 at 7:36

    I have downloaded the file and have the same exception, though file seems to be legit.

    Maybe you should use zipfile instead:

    >>> import zipfile
    >>> zipfile.ZipFile( 'you-get-0.4.1128.zip' )
    <zipfile.ZipFile object at 0x7fc515343c50>
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.