Flask項目打包為單個exe文件運行?掌握原理后居然如此簡單!

      網友投稿 3639 2022-05-29

      python打包exe工具

      Python打包工具主要有三種:py2exe、PyInstaller和cx_Freeze。雖然是三種工具,但是實現打包的方式都是大同小異。無非將Python運行所需的基礎dll文件和源碼依賴的模塊篩選后聚合在一起,從而達到脫離環境單獨運行的目的。但其中比較新奇的是它們居然可以將最終代碼打包成單個文件去運行,簡直不要太神奇。清風常用的打包工具為pyinstaller,安裝下載簡單,網上的文檔也很齊全。

      打包的exe如何執行

      但凡大家看到python打包exe工具的優勢,都會提到一句**打包成單個文件,可以保護源碼不外泄。**對于新手來說,這個理由完美,單個文件怎么操作感覺也不會獲得源碼,但我只能說,天真啊!pyinstaller的官方文檔:pyinstaller.readthedocs.io:How the One-File Program Works中有相關內容的詳細說明,為了方便,我簡單翻譯下:

      引導加載程序也是單文件捆綁包的核心。啟動后,它將在此操作系統的相應臨時文件夾位置中創建一個臨時文件夾。該文件夾名為_MEIxxxxxx其中xxxxxx是一個隨機數。一個可執行文件包含腳本使用的所有Python模塊的嵌入式歸檔,以及任何非Python支持文件(例如,.so文件)的壓縮副本。引導加載程序解壓縮支持文件,并將副本寫入臨時文件夾。這可能需要一些時間。這就是為什么單文件應用程序比單文件夾應用程序啟動慢的原因。

      所以單個的exe文件在執行時,會先在系統臨時目錄下創建一個_MEI開頭的文件夾,然后解壓源碼、依賴文件后,運行該臨時文件夾下的內容。其中windows的臨時文件夾通常為:

      C:\Windows\Temp_MEIxxxx 或

      C:\Users\用戶名\AppData\Local\Temp_MEIxxxx

      但經過多次測試,幾乎全在后者的目錄下。其實只要在cmd下輸入echo %temp% 或者 %tmp%就能確定了...

      Linux的臨時文件夾目錄自然是在: /tmp/_MEIxxxxx

      當然,如果每次exe執行時,都會創建臨時文件夾,但執行完成后又不銷毀,豈不是早就導致我們的電腦磁盤空間溢出了。所以官方是有說明的:

      創建臨時文件夾后,引導程序將在臨時文件夾的上下文中繼續與單文件夾捆綁軟件一樣進行。當捆綁的代碼終止時,引導加載程序將刪除臨時文件夾。如果程序崩潰或被殺死,則不會刪除該文件夾(在Unix上為kill -9,在Windows上為Task Manager殺死,在Mac OS上為“ Force Quit”)。因此,如果您的應用程序頻繁崩潰,則用戶將丟失磁盤空間到多個臨時文件夾。_MEIxxxxxx_MEIxxxxxx

      打包Flask項目

      pyinstalelr的基礎使用就不在這里過多介紹了,之前的文章有過詳細的說明:Python打包工具--Pyinstaller詳細介紹:https://mp.weixin.qq.com/s/smsO0n8M18J7ofoOsWEjoQ

      我們只需要知道pyinstaller -F(onefile)參數即可將代碼最終打包為單個的exe文件即可。但是Flask的static、templates該怎么打包呢?讓我們以之前開發過的一個FlaskHttpserver為例說明。首先看下代碼結構:

      settings中放了Flask的一些config配置,manage.py通過藍圖注冊HttpServer中views下的account與home模塊。那么,現在我們需要將代碼中的static、templates、settings(測試發現這個配置文件也沒辦法自動打包,需要手動追加)成單個文件呢?pyinstaller提供了一個

      [--add-data ]

      的參數,整體打包命令如下:

      pyinstaller?-F?-i?BreezePython.ico?--add-data="HttpServer\static;HttpServer\static"?--add-data="HttpServer\templates;Httpserver\templates"?--add-data="settings.py;."?manage.py

      原理就是保持代碼中的路徑一致,如果是當前路徑使用.進行替換。有些人覺得這個一個一個的添加太麻煩了,那么還有另一種思路。來看看我們打包后的目錄:

      打包完成后,會生成一個main應用.spec的文件,通過我們剛才一頓--add-data的操作后,spec有什么區別么?

      所以我們可以換另一種方式加載依賴文件:

      首次打包時直接-F 完成打包

      編輯*.spec文件,通過在列表中添加對應元祖信息的方式,追加以來穩健

      pyinstaller -F *.spec進行二次打包即可追加文件至exe中。

      來讓我們看看打包后的exe是否可以執行吧:

      OK,一個exe文件拉起整個Flask項目,帶著exe我們就可以脫離環境單獨運行我們的HTTPServer了。是不是很炫酷?

      Flask項目能打包為單個exe文件運行?掌握原理后居然如此簡單!

      臨時文件監控復制

      初次測試,可能存在打包路徑錯誤的問題,每次去找臨時路徑查看太麻煩了,既然寫代碼,不如順手寫個動態監控_MEI路徑并完成循環復制的功能,具體實現如下:

      判斷電腦的操作系統

      while循環監控臨時目錄

      啟動exe工具

      獲取exe創建的_MEI開頭文件夾

      將該臨時文件夾拷貝到執行目錄

      最終代碼實現如下:

      #?-*-?coding:?utf-8?-*- #?@Author???:?王翔 #?@微信號???:?King_Uranus #?@公眾號????:?清風Python #?@GitHub???:?https://github.com/BreezePython #?@Date?????:?2020/11/17?23:50:09 #?@Software?:?PyCharm #?@version??:Python?3.7.3 #?@File?????:?get_source_code.py import?platform import?os import?time import?shutil def?get_tmp_path(): ????if?platform.platform().lower().startswith('windows'): ????????return?os.getenv('temp') ????else: ????????return?'/tmp' class?GetSourceCode: ????def?__init__(self): ????????self.base_path?=?os.path.dirname(__file__) ????????self.tmp_path?=?get_tmp_path() ????????self.basic_dirs?=?self.get_dirs() ????????self.code_dir?=?None ????def?get_dirs(self): ????????for?root,?dirs,?files?in?os.walk(self.tmp_path): ????????????return?set(dirs) ????def?get_source_dir(self): ????????while?True: ????????????_dir?=?list(self.get_dirs()?-?self.basic_dirs) ????????????if?_dir?and?_dir[0].startswith('_MEI'): ????????????????self.code_dir?=?_dir[0] ????????????????print("find?source?code?dir?%s"?%?self.code_dir) ????????????????break ????????????else: ????????????????time.sleep(0.2) ????????self.copy_code_dir() ????def?copy_code_dir(self): ????????abs_tmp_path?=?os.path.join(self.tmp_path,?self.code_dir) ????????while?os.path.exists(abs_tmp_path): ????????????source_path?=?os.path.join(self.base_path,?self.code_dir) ????????????if?not?os.path.exists(source_path): ????????????????os.mkdir(source_path) ????????????for?root,?dirs,?files?in?os.walk(abs_tmp_path): ????????????????for?file?in?files: ????????????????????remote_path?=?root.replace(abs_tmp_path,?source_path).replace('\\',?'/') ????????????????????if?not?os.path.exists(remote_path): ????????????????????????print(remote_path) ????????????????????????os.makedirs(remote_path) ????????????????????if?not?os.path.exists(remote_path?+?'/'?+?file): ????????????????????????shutil.copy(os.path.join(root,?file),?remote_path) ????????print("Get?source?code?end.") if?__name__?==?'__main__': ????print("start?Source?Code?Analyse?project.") ????print("Monitoring?source?files...") ????g?=?GetSourceCode() ????g.get_source_dir()

      看看效果如何:

      ok,快把你積攢已久的代碼篩選下,看看那些適合打包成exe,拿去給朋友們炫耀吧!關于FlaskHttpserver,如果需要的朋友可以后臺回復 服務 進行下載。

      -------

      本文轉自:清風Python公眾號

      Python

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:第三章: C語言程序設計初步-語句學習(上)
      下一篇:華為云文檔數據庫服務DDS監控告警全新優化
      相關文章
      亚洲日本va在线观看| 亚洲成A人片在线观看无码不卡| 亚洲精品视频在线看| 亚洲AV永久无码精品网站在线观看| 亚洲人色大成年网站在线观看| 久久久亚洲欧洲日产国码aⅴ| 久久精品7亚洲午夜a| 亚洲色婷婷综合久久| 亚洲中文字幕无码久久精品1| 亚洲情a成黄在线观看| 亚洲国产日韩成人综合天堂 | 亚洲AV无码一区二区乱孑伦AS| 亚洲宅男天堂在线观看无病毒| 亚洲伊人久久综合中文成人网| 亚洲AⅤ优女AV综合久久久| 亚洲 自拍 另类小说综合图区| 日日摸日日碰夜夜爽亚洲| 国产精品亚洲小说专区| 青青青亚洲精品国产| 国产亚洲视频在线播放大全| 色五月五月丁香亚洲综合网| 伊人久久亚洲综合影院| 亚洲第一区精品观看| 亚洲人成电影在线播放| 亚洲国产午夜福利在线播放 | 国产综合激情在线亚洲第一页| 久久亚洲AV成人无码国产电影| 99亚洲乱人伦aⅴ精品| 国产亚洲福利精品一区二区| 亚洲精品99久久久久中文字幕 | 亚洲熟妇无码一区二区三区| 亚洲xxxx视频| 亚洲日本乱码卡2卡3卡新区| 亚洲人成电影网站免费| 毛片亚洲AV无码精品国产午夜| 亚洲国产精品无码久久久久久曰| 久久久久亚洲AV无码专区桃色| 亚洲熟妇无码另类久久久| 亚洲人成网77777亚洲色| 亚洲国产精久久久久久久| 亚洲小视频在线播放|