我用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”库。
即使将解决方案打包到 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 操作系统,但基本上您只需要转到站点包所在的位置:)