在 python 中编译我的代码时,pdfium 库无法工作

问题描述 投票:0回答:1

我用Python编程语言编写了一个程序,将pdf文件转换为jpg文件。我在前端部分使用了“eel”库。 VS Code 中一切正常。我使用 pdfium 库将 PDF 转换为 jpg 文件。我使用 pyinstaller 编译了应用程序代码。 pdfium 库在启动前出现问题。

func.py:

import pandas as pd
import requests
from urllib.parse import urlencode
from datetime import datetime
import pypdfium2 as pdfium
import win32com.client as win32
from pywintypes import com_error
import psutil
import time,os
import openpyxl as xl 
def ExceltoImage(excelfile):
    for proc in psutil.process_iter():
        if proc.name() == "EXCEL.EXE":
            proc.kill()
    wbx = xl.load_workbook(excelfile) 
    print(wbx.sheetnames[0])
    pdffile = os.path.join(os.getcwd(),'temp','template.pdf')
    excel = win32.gencache.EnsureDispatch('Excel.Application')
    wb = excel.Workbooks.Open(excelfile)
    time.sleep(7)
    # ws = wb.WorkSheets(1).Select()
    ws = wb.Worksheets(wbx.sheetnames[0]).Select()
    # Save
    wb.ActiveSheet.ExportAsFixedFormat(0, pdffile)
    time.sleep(7)
    wb.Close()
    excel.Quit()
    time.sleep(2)
    pdf = pdfium.PdfDocument(pdffile)
    imgs = []
    for i in range(len(pdf)):
        img = os.path.join(os.getcwd(),'temp',f'template{i:03d}.jpg')
        page = pdf[i]
        image = page.render(scale=4).to_pil()
        image.save(img)
        imgs.append(img)
    return imgs
def ExceltoImageHeader(pdffile):
    pdf = pdfium.PdfDocument(pdffile)
    imgs = []
    for i in range(len(pdf)):
        img = os.path.join(os.getcwd(),'temp',f'header{i:03d}.jpg')
        page = pdf[i]
        image = page.render(scale=4).to_pil()
        image.save(img)
        imgs.append(img)
    return imgs
def getImgData(file):
    excel_data = pd.read_excel(file,usecols="A,B,C,D")
    data = pd.DataFrame(excel_data)
    d = data.values.tolist()
    newdata = []
    for tr,x in enumerate(d):
        if tr==0:
            continue
        if str(x[2])!='nan' and str(x[3])!='nan':            
            newdata.append(x)
    return newdata
def getImgList(file):
    excel_data = pd.read_excel(file,usecols="C")
    data = pd.DataFrame(excel_data)
    d = data.values.tolist()
    newdata = []
    for tr,x in enumerate(d):
        if tr<7:
            continue
        if str(x[0])!='nan':            
            newdata.append(x)
    print(type(newdata),newdata)
    newdata = list(dict.fromkeys(newdata))
    return newdata
def getyandex(linkimg):   
    name = os.path.basename(linkimg)
    image_name = os.path.join(os.getcwd(),'temp',name)
    print(linkimg)
    headers = requests.utils.default_headers()

    headers.update(
        {
            'User-Agent': 'My User Agent 1.0',
        }
    )
    r = requests.get(linkimg, stream=True,headers=headers)
    if r.status_code==200:
        with open(image_name, 'wb') as f:
            for chunk in r.iter_content():
                f.write(chunk)
        if(os.path.exists(image_name)):
            return image_name
        else:
            return False
    else:
        return False

main.py:

    from fpdf import FPDF
import os,json,datetime
from func import getImgData,getImgList,getyandex,ExceltoImage,ExceltoImageHeader
class FPDF(FPDF):
    
    def header(self):
        f = open(os.path.join(os.getcwd(),'template','setting.json'),encoding="UTF-8")
        setting = json.load(f)
        # Устанавливаем лого
        self.image('template/logo.jpg', 8, 6, 25)
        self.add_font('sysfont', '', r"c:\WINDOWS\Fonts\timesi.ttf", uni=True)
        self.set_font('sysfont', '', 8)
 
        # Добавляем адрес
        self.cell(150)
        self.cell(0, 4, setting['company'], ln=1)
        self.cell(150)
        self.cell(0, 4, setting['inn'], ln=1)
        self.cell(150)
        self.cell(0, 4, setting['address'], ln=1)
        self.cell(150)
        self.cell(0, 4, setting['tel'], ln=1)
        self.cell(150)
        self.cell(0, 4, setting['email'], ln=1)

        # Разрыв линии
        self.ln(3)
 
    def footer(self):
        self.set_y(-10)
        self.set_font('Arial', 'I', 8)
 
        # Добавляем номер страницы
        page =  str(self.page_no()) + '/{nb}'
        self.cell(0, 10, page, 0, 0, 'C')
 
def create_pdf(smetfile,imgsfile):
    f = open(os.path.join(os.getcwd(),'template','setting.json'),encoding="UTF-8")
    setting = json.load(f)
    pdf = FPDF()
    # Создаем особое значение {nb}
    pdf.alias_nb_pages()
    # part 1
    
    pdf.add_page()
    pdf.add_font('Times', '', r"c:\WINDOWS\Fonts\timesbd.ttf", uni=True)
    pdf.set_font('Times', '', 14)
    pdf.cell(0, 5, txt=setting['header_1'], ln=1,align='C')
    pdf.cell(0, 5, txt=setting['header_2'], ln=1,align='C')
    pdf.cell(0, 3, txt="", ln=1,align='C')
    pdf.cell(0, 5, txt=setting['header_3'], ln=1,align='C')
    pdf.cell(0, 5, txt="", ln=1,align='C')
    listimg = getImgList(smetfile)
    dataimg = getImgData(imgsfile)
    if len(listimg)>0 and len(dataimg)>0:
        for indx,ls in enumerate(listimg):
            if indx>1 and indx%2==0:
                pdf.add_page()
            getindex = False
            for index,img in enumerate(dataimg):
                if img[0]==ls[0]:
                    getindex = index
            if getindex==False:
                print("Not Found")
                continue
            else:
                name = dataimg[getindex][0].strip()
                typeimg = dataimg[getindex][1].strip()
                imglink = dataimg[getindex][2].strip()
                videolink = dataimg[getindex][3].strip()
            if typeimg=='Не отображаем' or imglink=='Без изображения':
                continue
            pdf.cell(0, 10, txt=name, ln=1,align='C')
            pdf.cell(30)
            print(imglink)
            imglink = 'https://prokarniz.ru/wp-content/uploads/2017/09/elektricheskiy-karniz-novokitay-2-380x260.jpg'
            img = getyandex(imglink)
            if img==False:
                print("Not Found 404")
                continue
            if os.path.exists(img):
                pdf.image(img,w=130)
            else:
                continue
            if videolink!='Без видео':
                pdf.cell(0, 10, txt=videolink, ln=1,align='C',link=videolink)
            pdf.cell(10,ln=1)

    
    
    # part 2
            # pdf.set_margins(0,0,0)
    pdf.add_page("L")
    # pathxlsx = os.path.join(os.getcwd(),'template','template.xlsx')
    imgs = ExceltoImage(smetfile)
    # pdf.cell(20)
    if len(imgs)>0:
        for imgxx in imgs:
            pdf.image(imgxx,10,30,w=280,h=180)


    # part 3
    pdf.add_page('P')
    pdf.add_font('Times', '', r"c:\WINDOWS\Fonts\timesbd.ttf", uni=True)
    pdf.set_font('Times', '', 14)
    pathxlsxheader = os.path.join(os.getcwd(),'template','footer.pdf')
    imgs = ExceltoImageHeader(pathxlsxheader)
    # pdf.cell(20)
    if len(imgs)>0:
        for imgxx in imgs:
            pdf.image(imgxx,0,30,w=200,h=260)

    now = datetime.datetime.now()
    string = now.strftime('%Y%m%d%H%M%S')
    pathtopdf = os.path.join(os.getcwd(),'output',f'result_{string}.pdf')
    pdf.output(pathtopdf) 
# if __name__ == '__main__':
#     create_pdf('output/header_footer.pdf')

app.py

    import main
import eel,os
import tkinter 
import tkinter.filedialog as filedialog
if __name__ == '__main__':
    # pathsmet = ''
    # pathimages = ''
    @eel.expose
    def run(pathsmet,pathimages):
        print(pathsmet,pathimages)
        if os.path.exists(pathsmet) and os.path.exists(pathimages):
            pdfpathname = main.create_pdf(pathsmet,pathimages)
            return pdfpathname
        else:
            return "NO"
    @eel.expose
    def selectFolder(type):
        print("Here")
        root = tkinter.Tk()
        root.attributes("-topmost", True)
        root.withdraw()
        filetypes = (
            ('Excel', '*.xlsx'),
            ('All files', '*.*')
        )
        directory_path = filedialog.askopenfilename(
        title='Excel file',
        initialdir='/',
        filetypes=filetypes)
        
        if type=='smet':
            pathsmet=directory_path
            print(pathsmet)
            return str(pathsmet)
        if type=='imgs':
            pathimages=directory_path
            print(pathimages)
            return str(pathimages)

    chrome = os.path.join(os.getcwd(),'template','chrome-win','chrome.exe')
    front = os.path.join(os.getcwd(),'template','front')
    eel.init(front)

    eel.browsers.set_path("chrome", chrome)

    eel.start('index.html', mode="chrome", size=(760, 760))

py -m eel app.py web


回溯(最近一次调用最后一次): 文件“app.py”,第 1 行,位于 文件“PyInstaller\loader\pyimode2_importers.py”,第 419 行,在 exec_module 文件“main.py”,第 3 行,在 文件“PyInstaller\loader\pyimode2_importers.py”,第 419 行,在 exec_module 文件“func.py”,第 5 行,在 文件“PyInstaller\loader\pyimode2_importers.py”,第 419 行,在 exec_module 文件“pypdfium2_init.py”,第 4 行,在 文件“PyInstaller\loader\pyimode2_importers.py”,第 419 行,在 exec_module 文件“pypdfium2_library_scope.py”,第 6 行,在 文件“PyInstaller\loader\pyimode2_importers.py”,第 419 行,在 exec_module 文件“pypdfium2”中 aw.py”,第 5 行,在 文件“PyInstaller\loader\pyimode2_importers.py”,第 419 行,在 exec_module 文件“pypdfium2_raw__init.py”,第 5 行,在 文件“PyInstaller\loader\pyimode2_importers.py”,第 419 行,在 exec_module 文件“pypdfium2_raw indings.py”,第 53 行,在 文件“pypdfium2_raw indings.py”,第 44 行,在 _register_library 中 文件“pypdfium2_raw indings.py”,第 37 行,在 _find_library 中 ImportError:找不到库“pdfium”(dirs=['.'],search_sys=False)[8092] 由于未处理的异常,无法执行脚本“app”!

VS Code 中一切正常。当我使用 pyinstallaer 刷新 EXE 时,出现错误,提示找不到“pdfium”库。

python pyinstaller eel pdfium
1个回答
0
投票

即使将解决方案打包到 EXE 中,pypdfium2 模块仍然会查找站点包中存在的一些文件。这些文件(“pdfium.dll”和两个不同的“version.json”)无处可寻。

我的解决方法是简单地使用 pyinstaller 的规范文件(或使用命令行选项 --add-data)将这些文件添加到正确的路径

因此,为此,您首先需要在计算机中安装 pypdfium2(最好在虚拟环境中),并在数据中包含包含以下元组的规范文件:

a = Analysis(
    ['your_project.py'],
    pathex=[],
    binaries=[],
    datas=[
        ('venv\\Lib\\site-packages\\pypdfium2_raw\\pdfium.dll', 'pypdfium2_raw'),
        ('venv\\Lib\\site-packages\\pypdfium2_raw\\version.json', 'pypdfium2_raw'),
        ('venv\\Lib\\site-packages\\pypdfium2\\version.json', 'pypdfium2')
    ],
    ...
)

或者,您可以使用 pyinstaller 命令将这些文件作为多个 --add-data 传递

pyinstaller --add-data "venv\Lib\site-packages\pypdfium2_raw\pdfium.dll;pypdfium2_raw" --add-data "venv\Lib\site-packages\pypdfium2_raw\version.json;pypdfium2_raw" --add-data "venv\Lib\site-packages\pypdfium2\version.json;pypdfium2" your_project.py

这里是规范文件的参考:https://pyinstaller.org/en/v4.0/spec-files.html

PS.:以上路径适用于名为 venv 的虚拟环境和 Windows 操作系统,但基本上您只需要转到站点包所在的位置:)

© www.soinside.com 2019 - 2024. All rights reserved.