1

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
  • 33,874
  • 19
  • 107
  • 152
iMath
  • 2,326
  • 2
  • 43
  • 75

2 Answers2

1

(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.

Community
  • 1
  • 1
ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
  • 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 https://bpaste.net/show/243292a2d4a6 – iMath Aug 14 '18 at 07: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 '18 at 07: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 '18 at 07: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 '18 at 07:36
  • @iMath That said, https://stackoverflow.com/questions/5366100/pyinstaller-but-keeping-py-files-upgradeable looks relevant from the information you gave. – ivan_pozdeev Aug 14 '18 at 07:41
  • Thanks for your tips , helped me a lot ! 1) I finally figured out the way to use the zip archive of the module: add the path to the zip archive to `sys.path` provided your zip archive having a directory named `you_get` to hold the files and folders which originally reside in `C:\Users\i\Downloads\you-get-0.4.1128\src\you_get` when unpacked , [here](https://stackoverflow.com/questions/51914467/directory-hierarchy-issue-when-using-shutil-make-archive) is a relevant way to make the archive . – iMath Aug 20 '18 at 09:07
  • 2) I also figured out the way to use pyinstaller to fit my case thanks to the thread you referenced to, and my answer [here](https://stackoverflow.com/a/51927313/1485853). 3) The Python `zipimport` module is incompatible with old version of ZIP format specification, is this a bug ? – iMath Aug 20 '18 at 09:07
  • @iMath _"[in a] zip archive... a directory named `you_get` [with] files [from] `you-get-0.4.1128\src\you_get`"_ -- this is exactly what `setup.py install bdist_egg` and `setup.py bdist --format=zip` do in the case of a pure-Python package (in case of an extension one, they also compile the C sources and package the result in the same manner). [`.egg` in particular is specifically designed to be importable](https://packaging.python.org/discussions/wheel-vs-egg/). – ivan_pozdeev Aug 20 '18 at 10:17
  • 1
    @iMath Looked deeper. This is a bug. – ivan_pozdeev Aug 20 '18 at 11:48
0

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>
>>>
lenik
  • 23,228
  • 4
  • 34
  • 43