Home Pyinstaller 打包後執行檔位置 in MacOS(中文)
Post
Cancel

Pyinstaller 打包後執行檔位置 in MacOS(中文)

應用程式執行位置

當我們使用 pyinstaller 將我們的 python 程式打包成執行檔後,如果牽涉到讀寫檔的程式,Windows 和 MacOS 的執行狀況會不太一樣,如下圖,我們有個執行檔和一個檔案。

Desktop View

執行檔只是一個簡單的讀檔程式

1
2
with open("myfile.txt", "a", encoding="utf-8") as file: 
    file.write("I am here! \n")

在 Windows 上,不論你把他們放在哪個資料夾上,執行都正常。

但在 MacOS 上就會找不到檔案,好像你的應用程式和你的檔案在不同的資料夾一樣。

這是因為在 macOS 上點擊使用 PyInstaller 打包的執行檔時,執行檔的當下目錄(current working directory, CWD)通常並非執行檔本身所在的目錄,這是因為應用程式會在一個稱為「沙盒」的環境中運行。

沙盒機制的目的

macOS 上的沙盒(Sandbox)是一種安全機制,用於限制應用程式對系統和用戶資料的訪問,從而提高整個系統的安全性和穩定性。以下是有關 macOS 沙盒的一些詳細解釋:

隔離

沙盒將每個應用程式隔離開來,限制它們對其他應用程式、系統資源和用戶資料的訪問。這可以防止一個應用程式中的漏洞影響到其他部分。

安全性

通過限制應用程式的訪問範圍,沙盒可以減少惡意軟體對系統的危害。例如,一個在沙盒內運行的應用程式即使被攻擊者利用,也無法訪問系統的敏感區域或其他應用程式的資料。

隱私

沙盒機制保護用戶的隱私,確保應用程式只能訪問被明確授權的資料。例如,一個應用程式需要明確請求權限才能訪問用戶的照片或聯絡人。

很多人都有這樣的經驗,在 macOS 的裝置上不太容易中病毒,就是因為 macOS 的沙盒機制可以顯著提高系統的安全性,讓系統不容易中病毒。

解法

如何解決上述 macOS 執行檔與檔案的位置不一致問題 ? 解法很簡單,就是在你的程式中加入當前執行檔的位置就行啦!

完整的 code 如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import os
import sys

def get_resource_path(relative_path):
    """獲取資源檔案的絕對路徑"""
    if getattr(sys, 'frozen', False):
        # 如果是打包後的程式
        base_path = os.path.dirname(sys.executable)
    else:
        # 如果是原始 Python 腳本
        base_path = os.path.dirname(os.path.abspath(__file__))

    return os.path.join(base_path, relative_path)

with open(get_resource_path("myfile.txt"), "a", encoding="utf-8") as file:  
    file.write("I am here! \n")

這時候打包後的執行檔,在 Windows 和 macOS 都可以正確讀寫檔案了。

That’s all.

☝ツ☝

This post is licensed under CC BY 4.0 by the author.

👈 ツ 👍