简体   繁体   English

在使用 pyinstaller 制作的可执行文件中使用 pyunpack 并结合 try except

[英]Use pyunpack inside an executable file made with pyinstaller in combination with try except

I have a strange behaviour for pyunpack, a package for unpacking, inside an executable.我对 pyunpack 有一个奇怪的行为,一个用于解包的包,在一个可执行文件中。

I want to do the following thing:我想做以下事情:

I have a .7z type of file whose ending is not in .7z but in .sent.我有一个 .7z 类型的文件,其结尾不是 .7z 而是 .sent。

First I try to unzip it the direct way, which leads to an expected error that is caught.首先,我尝试以直接方式解压缩它,这会导致捕获到预期的错误。

Inside this error catching, I am first adding the .7z extension, then I am unzipping the file properly into a folder called "grog", then I give the zipped file its original name back.在此错误捕获中,我首先添加 .7z 扩展名,然后将文件正确解压缩到名为“grog”的文件夹中,然后将压缩文件的原始名称恢复为原来的名称。

Here is the code below:这是下面的代码:

# test.py
from os.path import abspath, join, exists, dirname
from os import rename, mkdir
from shutil import copy
import multiprocessing
import pyunpack

multiprocessing.freeze_support()
print(0)
name = "file_to_be_unzipped.sent"
print("a")
path = "C:\\Users\\myname\\eclipse-workspace-tms\\test_unzip_exe"
print(abspath("."))
print("b")
unzip_dest = join(path, "grog")
if not exists(unzip_dest):
    mkdir(unzip_dest)
print("c")
name = join(path, name)
print("d")
print("e")
try:
    print(1)
    pyunpack.Archive(name).extractall(unzip_dest)
    print(2)
except pyunpack.PatoolError as pterr:
    print(3)
    temp_f_name = name + ".7z"
    print(4)
    rename(name, temp_f_name)
    try:
        print(5)
        pyunpack.Archive(temp_f_name).extractall(unzip_dest)
        print(6)
        rename(temp_f_name, name)
        print(7)
    except pyunpack.PatoolError as pterr2:
        # removing useless 7z extension
        print(8)
        rename(temp_f_name, name)
        print(9)
        # Case when the file is already unzipped
        if str(pterr2).find("Is not archive"):
            print(10)
            copy(name, unzip_dest)
            print(11)
        print(12)
except ValueError as v:
    print(13)
    print(v)
    print(14)

When I launch the script test.py, I get the expected behaviour:当我启动脚本 test.py 时,我得到了预期的行为:

0
a
C:\Users\myname\eclipse-workspace-tms\test_unzip_exe
b
c
d
e
1
3
4
5
6
7

then I build the executable with the following command line:然后我使用以下命令行构建可执行文件:

pyinstaller --log-level=DEBUG test.spec

and the following spec file:以及以下规范文件:

# -*- mode: python ; coding: utf-8 -*-

block_cipher = None

import pyunpack
import patoolib
from pyunpack import Archive, PatoolError
from patoolib.programs import ar
from patoolib.programs import  arc
from patoolib.programs import  archmage
from patoolib.programs import  arj
from patoolib.programs import  bsdcpio
from patoolib.programs import  bsdtar
from patoolib.programs import  bzip2
from patoolib.programs import  cabextract
from patoolib.programs import  chmlib
from patoolib.programs import  clzip
from patoolib.programs import  compress
from patoolib.programs import  cpio
from patoolib.programs import  dpkg
from patoolib.programs import  flac
from patoolib.programs import  genisoimage
from patoolib.programs import  gzip
from patoolib.programs import  isoinfo
from patoolib.programs import  lbzip2
from patoolib.programs import  lcab
from patoolib.programs import  lha
from patoolib.programs import  lhasa
from patoolib.programs import  lrzip
from patoolib.programs import  lzip
from patoolib.programs import  lzma
from patoolib.programs import  lzop
from patoolib.programs import  mac
from patoolib.programs import  nomarch
from patoolib.programs import  p7azip
from patoolib.programs import  p7rzip
from patoolib.programs import  p7zip
from patoolib.programs import  pbzip2
from patoolib.programs import  pdlzip
from patoolib.programs import  pigz
from patoolib.programs import  plzip
from patoolib.programs import  py_bz2
from patoolib.programs import  py_echo
from patoolib.programs import  py_gzip
from patoolib.programs import  py_lzma
from patoolib.programs import  py_tarfile
from patoolib.programs import  py_zipfile
from patoolib.programs import  rar
from patoolib.programs import  rpm
from patoolib.programs import  rpm2cpio
from patoolib.programs import  rzip
from patoolib.programs import  shar
from patoolib.programs import  shorten
from patoolib.programs import  star
from patoolib.programs import  tar
from patoolib.programs import  unace
from patoolib.programs import  unadf
from patoolib.programs import  unalz
from patoolib.programs import  uncompress
from patoolib.programs import  unrar
from patoolib.programs import  unshar
from patoolib.programs import  unzip
from patoolib.programs import  xdms
from patoolib.programs import  xz
from patoolib.programs import  zip
from patoolib.programs import  zoo
from patoolib.programs import  zopfli
from patoolib.programs import  zpaq


# from pyunpack import Archive, PatoolError

a = Analysis(['test.py'],
             pathex=['C:\\Users\\myname\\eclipse-workspace-tms\\test_unzip_exe'],
             binaries=[],
             datas=[],
             hiddenimports=['pyunpack', 'patoolib',
                             'patoolib.programs.ar',
                             'patoolib.programs.arc',
                             'patoolib.programs.archmage',
                             'patoolib.programs.arj',
                             'patoolib.programs.bsdcpio',
                             'patoolib.programs.bsdtar',
                             'patoolib.programs.bzip2',
                             'patoolib.programs.cabextract',
                             'patoolib.programs.chmlib',
                             'patoolib.programs.clzip',
                             'patoolib.programs.compress',
                             'patoolib.programs.cpio',
                             'patoolib.programs.dpkg',
                             'patoolib.programs.flac',
                             'patoolib.programs.genisoimage',
                             'patoolib.programs.gzip',
                             'patoolib.programs.isoinfo',
                             'patoolib.programs.lbzip2',
                             'patoolib.programs.lcab',
                             'patoolib.programs.lha',
                             'patoolib.programs.lhasa',
                             'patoolib.programs.lrzip',
                             'patoolib.programs.lzip',
                             'patoolib.programs.lzma',
                             'patoolib.programs.lzop',
                             'patoolib.programs.mac',
                             'patoolib.programs.nomarch',
                             'patoolib.programs.p7azip',
                             'patoolib.programs.p7rzip',
                             'patoolib.programs.p7zip',
                             'patoolib.programs.pbzip2',
                             'patoolib.programs.pdlzip',
                             'patoolib.programs.pigz',
                             'patoolib.programs.plzip',
                             'patoolib.programs.py_bz2',
                             'patoolib.programs.py_echo',
                             'patoolib.programs.py_gzip',
                             'patoolib.programs.py_lzma',
                             'patoolib.programs.py_tarfile',
                             'patoolib.programs.py_zipfile',
                             'patoolib.programs.rar',
                             'patoolib.programs.rpm',
                             'patoolib.programs.rpm2cpio',
                             'patoolib.programs.rzip',
                             'patoolib.programs.shar',
                             'patoolib.programs.shorten',
                             'patoolib.programs.star',
                             'patoolib.programs.tar',
                             'patoolib.programs.unace',
                             'patoolib.programs.unadf',
                             'patoolib.programs.unalz',
                             'patoolib.programs.uncompress',
                             'patoolib.programs.unrar',
                             'patoolib.programs.unshar',
                             'patoolib.programs.unzip',
                             'patoolib.programs.xdms',
                             'patoolib.programs.xz',
                             'patoolib.programs.zip',
                             'patoolib.programs.zoo',
                             'patoolib.programs.zopfli',
                             'patoolib.programs.zpaq'],
             # hiddenimports=['Archive', 'PatoolError'],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          [],
          exclude_binaries=True,
          name='test',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=True )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               upx_exclude=[],
               name='test')

and then after an unexpected long time, I get the following:然后在意外的很长时间之后,我得到以下信息:

0
a
C:\Users\myname\eclipse-workspace-tms\test_unzip_exe\dist\test
b
c
d
e
1
2

where the file in the destination ("grog") is not an unzipped file as wanted but simply a copy.其中目标(“grog”)中的文件不是所需的解压缩文件,而只是一个副本。

Does anybody have an idea of what is going wrong?有人知道出了什么问题吗?

Thanks a lot非常感谢

EDIT:编辑:

I have made some progress: In the script, after print(1), if I add:我取得了一些进展:在脚本中,在 print(1) 之后,如果我添加:

sys.executable = "C:\\\\Users\\\\myname\\\\AppData\\\\Local\\\\Continuum\\\\anaconda3\\\\python.exe"

Then it works again.然后它再次工作。 However I have a non portable .exe但是我有一个不可移植的 .exe

Since importing only the python.exe file via the spec file is not enough, the other solution would be to add into the spec file由于仅通过spec文件导入python.exe文件是不够的,另一种解决方案是添加到spec文件中

("C:\\\\Users\\\\myname\\\\AppData\\\\Local\\\\Continuum\\\\anaconda3\\*,'.'")

which is going to make a huge executable, or pick one by one only the necessary files through trial and error, which takes ages.这将制作一个巨大的可执行文件,或者通过反复试验仅选择必要的文件,这需要很长时间。 Any elegant solution is welcome.欢迎任何优雅的解决方案。

EDIT 2: For more insight, the part from the pyunpack where the bug occurs is at the init file located in:编辑 2:为了更深入地了解,pyunpack 中出现错误的部分位于位于以下位置的init文件中:

"C:\\\\Users\\\\myname\\\\AppData\\\\Local\\\\Continuum\\\\anaconda3\\\\Lib\\\\site-packages\\\\pyunpack\\\\__init__.py"

in the function extract_all_patool:在函数 extract_all_patool 中:

   `p = EasyProcess([
        sys.executable,
        patool_path,
        '--non-interactive',
        'extract',
        self.filename,
        '--outdir=' + directory
        # '--verbose'
    ]).call(timeout=self.timeout) `

the problem being that sys.executable is set to the test.exe file instead of the python.exe executable itself问题是 sys.executable 设置为 test.exe 文件而不是 python.exe 可执行文件本身

EDIT3: I found a semi-portable solution, not ideal but I found nothing better yet: EDIT3:我找到了一个半便携式解决方案,不理想,但我还没有发现更好的:

The end-user is expected to install anaconda in the default path, then pip install patool and pip install pyunpack , and then copy the exe file anywhere in his username folder.最终用户应该在默认路径中安装 anaconda,然后pip install patoolpip install pyunpack ,然后将 exe 文件复制到他的用户名文件夹中的任何位置。

On my side: I am adding in the spec file import pathlib , from pathlib import Path In the hidden_mports list of the spec file, I am adding: 'pathlib', 'pathlib.Path',在我这边:我在规范文件中添加import pathlib , from pathlib import Path在规范文件的 hidden_​​mports 列表中,我添加: 'pathlib', 'pathlib.Path',

Then in the code, after print(1) , I am adding:然后在代码中,在print(1) ,我添加:

abspath = abspath(".")
user_path = Path(abspath).parts
user_path = join(user_path[0], user_path[1], user_path[2], user_path[3] )
conda_path = join("AppData", "Local", "Continuum", "anaconda3", "python.exe")
sys.executable = join(user_path, conda_path)

The problem is, as you found in your 2nd edit, that pyunpack needs patool installed on the target system - which, in turn, requires python.问题是,正如您在第二次编辑中发现的那样, pyunpack需要在目标系统上安装patool - 而这又需要 python。

To fix this you need to:要解决此问题,您需要:

  • Use tarballs or zipfiles;使用 tarball 或 zipfiles; shutil supports theses. shutil支持论文。

  • Or require the end user to have python installed.或者要求最终用户安装 python。

Another way of putting it is that to use pyunpack with pyinstaller , you need python on the target system.另一种说法是,将pyunpackpyinstaller一起使用,您需要在目标系统上安装 python。

The output of print(abspath(".")) when running directly in python is:直接在python中运行时print(abspath("."))的输出是:

C:\Users\myname\eclipse-workspace-tms\test_unzip_exe

While running with pyinstaller is:使用 pyinstaller 运行时:

C:\Users\myname\eclipse-workspace-tms\test_unzip_exe\dist\test

Thus, the archive is not extracted in the dist\\test folder.因此,存档不会提取到dist\\test文件夹中。

Fix this by setting path to return value of abspath(".") instead of hard-coding it to C:\\Users\\myname\\eclipse-workspace-tms\\test_unzip_exe通过将path设置为abspath(".")返回值而不是将其硬编码到C:\\Users\\myname\\eclipse-workspace-tms\\test_unzip_exe

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM