当前位置: 首页 > 知识库问答 >
问题:

无法让pyinstaller使用--onefile和--noConsole

谈桐
2023-03-14

我有一个gui程序,我用它来处理扫描的pdf,并寻找带有二维码的页面,这告诉程序在哪里可以将pdf分成多个文件。我的程序本质上是一个函数列表,当每个步骤完成时,这些函数会一个接一个地相互调用。

我遇到麻烦的地方是当我试图用PyInstaller将它编译成exe时。我的程序作为python文件运行良好,并且在指定--noConsole和--onefile选项时也能正常工作。我不能工作的是当我两者都用的时候。出于某种原因,试图同时使用--onefile和--noConsole获得一个工作程序不可避免地会失败。它的靴子很好,但总是在同一部分失败。以下是失败部分的代码:

import PySimpleGUI as sg
import shutil
import pathlib
from pyzbar.pyzbar import decode
from pyzbar.pyzbar import ZBarSymbol
from json import loads
from pdf2image import convert_from_path
import fitz
import win32com.client
import win32timezone
import os
import os.path
from os import path
from datetime import datetime, timedelta
from sys import exit
import tempfile

def scan_reader(filepath):
    '''takes a filepath pointing to a pdf file and returns the number of pages, as well as any QR data that could be pulled from the pages'''

    # Converts the pdf into a list of images, one for each page
    images = convert_from_path(filepath, size = (500, None), dpi = 300, poppler_path = 'bin', grayscale=True)
    # For each page image: searches page for QR, and if qr is found it adds it to the page_qr_data dictionary in the format page number:qr data
    page_qr_data = {}
    for idx, image in enumerate(images):
        # Decode the QR image
        detectedBarcodes = decode(image, symbols=[ZBarSymbol.QRCODE])       
        # If not detected then continue to the next page
        if not detectedBarcodes:
            continue
        else:
            # If QR detected, adds the page number to page_qr_data as a key and makes a list of the qr data for the value
            page_qr_data[idx] = []
            for barcode in detectedBarcodes:
                page_qr_data[idx].append(barcode.data)

    return len(images), page_qr_data

def scan_reader_window():
    '''Presents the user with a list of files that have been pulled and asks them to select which ones they'd like to import'''
    files = os.listdir(temp_pdf_dir)
    receivers_dict = {}
    page_lengths = {}
    i = 0
    for file in files:
        if sg.one_line_progress_meter('Processing files...', i+1, len(files), f'(Step 2 of 2) Processing files...\n{file}', key = 'file_processor', orientation = 'horizontal'):
            filepath = f'{temp_pdf_dir}/{file}'
            page_lengths[file], raw_scan_data = scan_reader(filepath)
            for key, value in raw_scan_data.copy().items():
                if len(value) > 1:
                    del raw_scan_data[key]
                raw_scan_data[key] = value[0]
    
            for key, value in raw_scan_data.copy().items():
                try:
                    raw_scan_data[key] = loads(value)
                except:
                    del raw_scan_data[key]
    
            for key, value in raw_scan_data.copy().items():
                if 'DB_FILENAME: ' not in value:
                    del raw_scan_data[key]
                else:
                    raw_scan_data[key] = value[20:]
            receivers_dict[file] = raw_scan_data
            i += 1
        elif i == len(files)-1:
            filepath = f'{temp_pdf_dir}/{file}'
            page_lengths[file], raw_scan_data = scan_reader(filepath)
            for key, value in raw_scan_data.copy().items():
                if len(value) > 1:
                    del raw_scan_data[key]
                raw_scan_data[key] = value[0]
    
            for key, value in raw_scan_data.copy().items():
                try:
                    raw_scan_data[key] = loads(value)
                except:
                    del raw_scan_data[key]
    
            for key, value in raw_scan_data.copy().items():
                if 'DB_FILENAME: ' not in value:
                    del raw_scan_data[key]
                else:
                    raw_scan_data[key] = value[20:]
            receivers_dict[file] = raw_scan_data
            i += 1
        else:
            clutter = os.listdir(temp_pdf_dir)
            for file in clutter:
                os.remove(f'{temp_pdf_dir}/{file}')
            exit()

    
    layout = []

    for value in receivers_dict.values():
        for filename in value.values():
            layout.append([sg.Checkbox(filename, default = True, background_color = 'white')])

    window = sg.Window('Scans', resizable = True, icon = parker_icon).Layout([    [sg.Text('Check all of the scans you wish to import.')],
                                                                                    [sg.Column(layout, scrollable=True, background_color = 'white', size = (350,350), expand_x = True, expand_y = True, justification = 'center', key = 'scans_column')],
                                                                                    [sg.Text("Save location:"), sg.Input(default_text = 'F:/Receiving/Receivers', key = 'selected_files'), sg.FolderBrowse(initial_folder = 'F:/Receiving/Receivers')],
                                                                                    [sg.Button('Continue'), sg.Button('Cancel')]    ])
    while True:
        event, values = window.read()
        if event == sg.WIN_CLOSED or event=='Cancel':
            clutter = os.listdir(temp_pdf_dir)
            for file in clutter:
                os.remove(f'{temp_pdf_dir}/{file}')
            exit()
        elif event == "Continue":
            save_location = values.pop('selected_files')
            del values['Browse']

            page_download_dict = {}
            for filename in receivers_dict.keys():
                page_download_dict[filename] = {}

            for key, value in receivers_dict.items():
                for page, filename in value.items():
                    page_download_dict[key][filename] = [page]

            for key, value in page_download_dict.items():
                for idx, (po_key, page_list) in enumerate(reversed(value.items())):
                    if idx == 0:
                        page_list.append(page_lengths[key]-1)
                        start_page = page_list[0]
                    else:
                        page_list.append(start_page-1)
                        start_page = page_list[0]

            i = 0
            for value in page_download_dict.values():
                for v in value.values():
                    v.append(values[i])
                    i += 1

            window.close()
            pdf_split_page(page_download_dict, len(values), save_location)

同样,当指定了--noconsole或--onefile时,它可以作为python文件和exe完美地工作。只有当我尝试两者都做的时候,它才会失败,而我一辈子也想不出为什么。有人有什么想法吗?谢谢!

编辑:这似乎是一个poppler问题。我尝试使用--debug运行它,在它崩溃后,我得到弹出消息“无法获得页计数。poppler是否安装并在路径中?”我修改了代码,使其“poppler_path='bin'”,并将bin添加到我的规范文件中,如下所示:datas=[('d://coding/bin','bin')],但仍然没有成功。另外,因为它是被请求的,这里是来自pyinstaller的日志(对不起,当我从控制台复制if时,它会删除换行符,不知道如何更好地格式化):

共有1个答案

云景焕
2023-03-14

我终于找到了解决办法。问题出在subprocess.popen()上,我使用的pdf2image模块使用它。使用这里找到的方法,我可以修改文件pdf2image.py,现在我的程序可以同时使用--onefile和--noConsole。

 类似资料:
  • 问题内容: 我正在尝试使用构建一个包含文件和图标的单文件EXE。我一生无法忍受。 如果我这样做了,那么一切都很好。当我使用时,它(在运行编译的EXE时)找不到引用的其他文件。它找到DLL和其他所有东西,只是找不到两个映像。 我查看了运行EXE时生成的,并且文件确实在其中。当我将EXE放到该临时目录中时,它会找到它们。很困惑。 这就是我添加到.spec文件中的内容 我还要补充一点,我也尝试过不要将它

  • 我试图捆绑我的py脚本作为一个. exe使用PyInstaller 2.0。我可以捆绑脚本,但是在我的脚本中,我需要打开一个应该捆绑在exe中的文件(所以它是可移植的)。我做这个有困难... 在我的生活中。是的,我有 我使用PyInstaller 2.0,这在我的电脑上工作正常,但是如果我把exe转移到另一台电脑上,它就不能工作了...PyInstaller 2.0非常新,所以上面的文档很少,出版

  • 我试图添加一个图像到一个文件的PyInster产生。我读过很多问题/论坛,比如这个和那个,但仍然不起作用。 我知道对于一个文件操作,Pyinstller会产生一个临时文件夹,可以通过.然而,我不知道在我的脚本中应该在哪里添加这个. 请显示以下内容: 1-在哪里和如何应该添加?在python脚本中,还是在规范文件中? 2-要使用的确切命令是什么?我试过了 或 然后添加('myImag.png','i

  • 我正在尝试使用pyinstaller将一个cefpython1应用程序捆绑到一个exe中。我有一个工作规范文件,它为cefpython1示例创建了一个发行版,cefsimple: 项目文件可以在我的谷歌硬盘上找到。不关心设置。py,它包含一个py2exe构建,我在pyinstaller旁边玩这个构建。您需要Python2.7、Win32gui、cefpython1,当然还有pyinstaller软

  • 问题内容: 我正在尝试使用PyInstaller 1.5编译PyQt程序。当我使用– onedir(默认设置)时,以下两个程序对我来说都工作正常,但这会创建相当大的程序。我想使用– onefile选项,但是在运行创建的onefile应用程序时,出现错误消息: 这两个都发生此错误: 和这个: 有人有什么想法吗? 问题答案: 1,Pyinstaller不会创建比–onedir小的–onefile。运行

  • 下面是我的pom.xml: