應用程式執行位置
當我們使用 pyinstaller 將我們的 python 程式打包成執行檔後,如果牽涉到讀寫檔的程式,Windows 和 MacOS 的執行狀況會不太一樣,如下圖,我們有個執行檔和一個檔案。
執行檔只是一個簡單的讀檔程式
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.

