[英]Adding a data file in Pyinstaller using the onefile option
我正在嘗試將圖像添加到 Pyinstaller 生成的一個文件中。 我已經閱讀了很多問題/論壇,例如這個和那個,但仍然無法正常工作。
我知道對於一個文件操作,Pyinstller 會生成一個臨時文件夾,可以通過sys.MEIPASS
。 但是我不知道我應該在我的腳本中的哪個位置添加這個sys.MEIPASS
。
請出示以下資料:
1- 應在何處以及如何添加sys.MEIPASS
? 在 python 腳本或規范文件中?
2-使用的確切命令是什么? 我試過了
pyinstaller --onefile --windowed --add-data="myImag.png;imag" myScript.py
或者
pyinstaller --onefile --windowed myScript.py
然后將 ('myImag.png','imag') 添加到規范文件中,然后運行
pyinstller myScript.spec
沒有一個有效。
注意:我在 windows 7 下有 python 3.6
當使用 PyInstaller 打包為單個文件時,運行 .exe 會將所有內容解壓縮到 TEMP 目錄中的文件夾中,運行腳本,然后丟棄臨時文件。 臨時文件夾的路徑隨着每次運行而變化,但對其位置的引用作為sys._MEIPASS
添加到sys
中。
為了利用這一點,當您的 Python 代碼讀取任何也將打包到您的 .exe 中的文件時,您需要將文件位置更改為位於sys._MEIPASS
下。 換句話說,您需要將它添加到您的 Python 代碼中。
這是一個示例,當打包到單個文件時,使用您引用的鏈接中的代碼將文件路徑調整到正確的位置。
# data_files/data.txt
hello
world
# myScript.py
import sys
import os
def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
def print_file(file_path):
file_path = resource_path(file_path)
with open(file_path) as fp:
for line in fp:
print(line)
if __name__ == '__main__':
print_file('data_files/data.txt')
使用以下選項運行 PyInstaller 打包文件:
pyinstaller --onefile --add-data="data_files/data.txt;data_files" myScript.py
構建 myScript.exe 運行正常,可以打開和讀取打包的數據文件。
我使用了命令提示符命令而不是 .spec
該命令排除勻稱,然后將其添加回(我猜這會調用不同的導入過程)。 這顯示了如何添加文件夾而不僅僅是文件。
pyinstaller --clean --win-private-assemblies --onefile --exclude-module shapely --add-data C:\\Python27\\Lib\\site-packages\\shapely;.\\shapely --add-data C:\\Python27\\tcl\\tkdnd2.8;tcl main.py
我嘗試更改了我的 python 腳本的工作目錄,它似乎有效:
import os
import sys
os.chdir(sys._MEIPASS)
os.system('included\\text.txt')
我的 pyinstaller 命令:
pyinstaller --onefile --nowindow --add-data text.txt;included winprint.py --distpath .
一種更簡單的訪問臨時文件夾的方法,如果這樣做:
bundle_dir = getattr(sys, '_MEIPASS', path.abspath(path.dirname(__file__)))
data_path = os.path.abspath(path.join(bundle_dir, 'data_file.dat'))
從閱讀文檔中得到它
我整理了一個簡單的 function ,當您將*.py
文件作為腳本(即在調試器中或通過命令行)運行時從本地路徑獲取資源,或者在作為pyinstaller
單文件運行時從臨時目錄獲取資源可執行的
from pathlib import Path
def fetch_resource(resource_path: Path) -> Path:
try: # running as *.exe; fetch resource from temp directory
base_path = Path(sys._MEIPASS)
except AttributeError: # running as script; return unmodified path
return resource_path
else: # return temp resource path
return base_path.joinpath(resource_path)
這樣,如果您的腳本有任何硬編碼路徑,您可以按原樣使用它們,例如: self.iconbitmap(fetch_resource(icon_path)
和icon_path
將根據環境適當更新。
對於您希望以這種方式使用的任何資產,您需要告訴pyinstaller
--add-data
,例如:
pyinstaller -w -F --add-data "./src/assets/icons/appicon.icon;assets/icons"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.