打包工具選擇
我自己用PyQT5寫(xiě)了一個(gè)應(yīng)用程序,基本上都寫(xiě)好了,到了打包發(fā)布這個(gè)環(huán)節(jié),我知道的有兩個(gè)工具可以幫我打包分別是
Pyinstaller Cythonpyinstaller會(huì)給我打包成一個(gè)exe文件,把python解釋器、所有依賴(lài)包、各種DLL都打包在里面,然后最終出來(lái)一個(gè)exe文件,聽(tīng)上去是很好。 Cython會(huì)給打包成pyd文件,然后依靠包導(dǎo)入的方式完成啟動(dòng),不會(huì)生成exe文件,聽(tīng)上去沒(méi)有pyinstaller好 兩個(gè)工具的安裝都十分方便快捷:
pip install pyinstaller pip install Cython這兩個(gè)我都測(cè)試了,最終我選擇用Cython完成了打包發(fā)布。為什么不用pyinstaller,打包出來(lái)的exe文件比較大,然后各種命令行操作我也不太熟悉,已經(jīng)學(xué)廢了。然后打包完成之后各種DLL無(wú)法load跟找不到,時(shí)間不等人啊!最重要的,pyinstaller打包完成exe其實(shí)就是一個(gè)壓縮包,特別容易被反編譯跟逆向工程取得源碼!誰(shuí)讓我已經(jīng)用過(guò)這招,所以我猜別人也會(huì)用。 選擇Cython是轉(zhuǎn)C然后編譯生成的,想要逆向是十分困難,源碼保護(hù)會(huì)好點(diǎn),另外Cython打包只要一個(gè)腳本運(yùn)行一下就好啦,這個(gè)腳本還是我從網(wǎng)上的來(lái)的,感謝這個(gè)腳本作者!腳本隨便改了改,就可以直接使用了。
打包流程與目錄結(jié)構(gòu)
在開(kāi)始打包之前,先把一些非源碼的文件整理好,放在項(xiàng)目的資源文件夾下面,我有兩個(gè)資源文件夾分別是images跟models,它們就不用打包了。然后我把我的五個(gè)源碼文件夾
以dlcore為例,修改腳本,運(yùn)行package_installer,腳本我也貼出來(lái),有需求的自取,放到跟項(xiàng)目同層目錄下面,會(huì)自動(dòng)創(chuàng)建build文件夾的。
importsys,os,shutil,time fromdistutils.coreimportsetup fromCython.Buildimportcythonize start_time=time.time() curr_dir=os.path.abspath('.') parent_path=sys.argv[1]iflen(sys.argv)>1else"" setup_file=__file__.replace('/','\') build_dir="build" build_tmp_dir=build_dir+"/temp" s="#cython:language_level=3" defget_py(base_path=os.path.abspath('.'),parent_path='',name='ui',excepts=(),copyOther=False,delC=False): """ 獲取py文件的路徑 :parambase_path:根路徑 :paramparent_path:父路徑 :paramexcepts:排除文件 py文件的迭代器 """ full_path=os.path.join(base_path,parent_path,name) forfilenameinos.listdir(full_path): full_filename=os.path.join(full_path,filename) ifos.path.isdir(full_filename)andfilename!=build_dirandnotfilename.startswith('.'): forfinget_py(base_path,os.path.join(parent_path,name),filename,excepts,copyOther,delC): yieldf elifos.path.isfile(full_filename): ext=os.path.splitext(filename)[1] ifext==".c": ifdelCandos.stat(full_filename).st_mtime>start_time: os.remove(full_filename) eliffull_filenamenotinexceptsandos.path.splitext(filename)[1]notin('.pyc','.pyx'): ifos.path.splitext(filename)[1]in('.py','.pyx')andnotfilename.startswith('__'): path=os.path.join(parent_path,name,filename) yieldpath else: pass defpack_pyd(): #獲取py列表 module_list=list(get_py(base_path=curr_dir,parent_path=parent_path,excepts=(setup_file,))) try: setup( ext_modules=cythonize(module_list,compiler_directives={'language_level':"3"}), script_args=["build_ext","-b",build_dir,"-t",build_tmp_dir], ) exceptExceptionasex: print("error!",str(ex)) else: module_list=list(get_py(base_path=curr_dir,parent_path=parent_path,excepts=(setup_file,),copyOther=True)) module_list=list(get_py(base_path=curr_dir,parent_path=parent_path,excepts=(setup_file,),delC=True)) ifos.path.exists(build_tmp_dir): shutil.rmtree(build_tmp_dir) print("complate!time:",time.time()-start_time,'s') defdelete_c(path='.',excepts=(setup_file,)): ''' 刪除編譯過(guò)程中生成的.c文件 :parampath: :paramexcepts: ''' dirs=os.listdir(path) fordirindirs: new_dir=os.path.join(path,dir) ifos.path.isfile(new_dir): ext=os.path.splitext(new_dir)[1] ifext=='.c': os.remove(new_dir) elifos.path.isdir(new_dir): delete_c(new_dir) if__name__=='__main__': try: pack_pyd() exceptExceptionase: print(str(e)) finally: delete_c()最終build文件夾中生成對(duì)應(yīng)的pyd文件如下:
運(yùn)行完這些源碼文件夾把得到pyd文件分別拷貝到另外一個(gè)目錄下對(duì)應(yīng)文件夾中,最終我的打包好的目錄結(jié)構(gòu)如下:
其中requirements.txt里面是需要安裝第三方依賴(lài)庫(kù),在該目錄運(yùn)行命令行即可完成安裝:
pip install -r requirements.txt參考readme文件,可以完成OpenVINO2022、TensorRT8.x配置支持。 我手寫(xiě)了一個(gè)簡(jiǎn)單startup.bat文件,雙擊startup.bat即可運(yùn)行打包好的應(yīng)用!
@echo "try to run openvm" SET PYTHONPATH=.%PYTHONPATH% cd ui python application_ui.py
運(yùn)行截圖如下:
遇到的坑
最后說(shuō)一下,我用cython打包遇到的一個(gè)大坑:
我有個(gè)超類(lèi)ImageTask,然后里面定義幾個(gè)抽象方法,其中一個(gè)方法名是exec,誰(shuí)知道這個(gè)是cython無(wú)法解析的字符串,我猜可能因?yàn)榇a安全檢測(cè)無(wú)法通過(guò),所以一直給報(bào)截圖的錯(cuò)誤,后面我把這個(gè)方法名稱(chēng)從exec改成t_exec就可以把對(duì)應(yīng)的py文件轉(zhuǎn)pyd文件了。
使用pyinstaller打包時(shí)候會(huì)遇到
Error: geos_c.dll not found, required by hook-shapely.py
去下載geos_c.dll https://www.dll-files.com/geos_c.dll.html
然后扔到windows/system32里面去就好啦!
-
OpenCV
+關(guān)注
關(guān)注
31文章
635瀏覽量
41349 -
python
+關(guān)注
關(guān)注
56文章
4797瀏覽量
84688 -
pyqt5
+關(guān)注
關(guān)注
0文章
25瀏覽量
3402
原文標(biāo)題:PyQT5+OpenCV開(kāi)發(fā)的應(yīng)用如何打包發(fā)布?
文章出處:【微信號(hào):CVSCHOOL,微信公眾號(hào):OpenCV學(xué)堂】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論