簡體   English   中英

使用 onefile 選項在 Pyinstaller 中添加數據文件

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM