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

5

我在运行一个可执行文件中使用pyunpack包进行解压缩时,出现了奇怪的问题。

我想要做以下事情:

我有一个以.sent结尾而非.7z结尾的.7z类型文件。

首先我尝试直接解压它,这会导致一个预期的错误,被捕获。

在这个错误捕获中,我首先添加.7z扩展名,然后将文件正确地解压到名为"grog"的文件夹中,最后将压缩文件的原始名称返回。

下面是代码:

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

当我运行脚本 test.py 时,我得到了预期的行为:
0
a
C:\Users\myname\eclipse-workspace-tms\test_unzip_exe
b
c
d
e
1
3
4
5
6
7

然后,我使用以下命令行构建可执行文件:

pyinstaller --log-level=DEBUG test.spec

以下是规范文件:

# -*- 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')

然后在出乎意料的长时间等待之后,我收到了以下内容:

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

目标文件夹中的文件(“grog”)并不是所需的未解压文件,而只是一个副本。

有人知道出了什么问题吗?

非常感谢。

编辑:

我取得了一些进展: 在脚本中,如果我在print(1)后添加:

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

然后它又可以工作了。但是我有一个不便携式的.exe文件

由于仅通过spec文件导入python.exe文件还不够, 另一种解决方案是在spec文件中添加

(“C:\\Users\\myname\\AppData\\Local\\Continuum\\anaconda3 \\ *,'。')

这将产生一个巨大的可执行文件,或者通过试错逐个选择必要的文件,这需要很长时间。欢迎任何优雅的解决方案。

编辑2:为了更深入地了解,在pyunpack中出现错误的部分位于:

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

在extract_all_patool函数中。

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

问题在于sys.executable被设置为test.exe文件,而不是python.exe可执行文件本身。

编辑3: 我找到了一个半可移植的解决方案,虽然不理想,但我还没有找到更好的:

期望最终用户将anaconda安装在默认路径中,然后pip install patoolpip install pyunpack,然后将exe文件复制到任何一个用户名文件夹中。

在我的一面: 我在spec文件中添加import pathlibfrom pathlib import Path。 在spec文件的hidden_mports列表中,我添加了: 'pathlib','pathlib.Path',

然后,在代码中,在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)

@legorooj 或许你可以帮忙解决这个问题,我设置了一个赏金。 - Matt Dnv
注意:在代码中添加import patoolib也没有改变任何内容。 - Matt Dnv
添加 'pyunpack.cli''pyunpack.about' 也不会有任何改变。 - Matt Dnv
2
我正在关闭你在 GitHub 上发布的问题;SO 是这个问题的正确地方。请给我一天或两天的时间来解决它。 - Legorooj
@Legorooj,非常感谢,我添加了第二个EDIT,将问题定位在pyunpack方面,希望能帮到你。 - Matt Dnv
显示剩余4条评论
2个回答

1
问题是,正如您在第二次编辑中发现的那样,pyunpack需要在目标系统上安装patool,而patool又需要python。
要解决此问题,您需要:
  • 使用tarballs或zipfiles;shutil支持这些。

  • 或者要求最终用户安装python。

换句话说,要在目标系统上使用pyinstallerpyunpack,您需要安装python。

嘿@legorooj:抱歉回复晚了,我因为著名的covid病毒生病了12天。我想要更精确的解释:如果我理解正确,你的解决方案2似乎是我在编辑3中建议的内容(请否认)。你能否就你的解决方案1提供更多的细节说明?谢谢和问候。 - Matt Dnv
我也尝试过导入整个Anaconda,以节省逐个选择Anaconda文件的时间;但它仍然无法工作:除了制作一个巨大而笨重的可执行文件外,在脚本/ patool中还会产生新的错误。 - Matt Dnv
1
@MattDnv 至少目前我们所知道的是你是免疫的... https://docs.python.org/3/library/shutil.html#shutil.unpack_archive 是你想要的函数,或者查看 tarfilezipfile 模块 - 两者都是标准库。是的,解决方案2等同于编辑3。 - Legorooj

-2

在 Python 直接运行 print(abspath(".")) 的输出结果为:

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

使用pyinstaller运行时是:

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

因此,存档文件不会在 dist\test 文件夹中解压。

通过将 path 设置为 abspath(".") 的返回值而不是硬编码为 C:\Users\myname\eclipse-workspace-tms\test_unzip_exe 来修复此问题。


感谢您回答Oluwafemi,但是在我看来,这并没有解决问题:我真的想要提取到文件夹中:path = "C:\\Users\\myname\\eclipse-workspace-tms\\test_unzip_exe\\grog"其中mkdir函数可以保证其存在。 - Matt Dnv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接