包裝成exe檔

      在〈包裝成exe檔〉中尚無留言

原因

辛苦寫出來的程式, 最終目地就是要給別人用的嘛(賣給別人賺錢啊), 不然是寫辛酸的然後孤芳自賞嗎. 回想當初, 為了寫Python的程式, 要先安裝Python解譯器!! 而當老闆叫你show一下你的成品時,  你總不能因為老闆的電腦沒裝Python解譯器而叫他等個半小時幫他下載安裝先吧.

為了要在一台沒有安裝Python解譯器的電腦上執行我們的成果, 最方便的就是在exe檔按二下直接執行. 但解譯器怎麼辦? 當然就是把解譯器包進exe檔裏, 這樣就不用安裝Python解譯器了.

準備

將 .py檔包裝成 .exe檔, 需要 pyinstaller這支程式, 請由下面指令載入

pip install pyinstaller

包裝

pyinstaller有一些參數可以下達

-F  : 要打包的 .py檔
-icon : 圖標路徑
-w : 使用視窗, 無控制台. wxPython也可以
-c : 使用控制台, 無視窗
–hidden-import=queue : 將相關模組全包進去

pyinstaller --hidden-import=queue -w -F .\win.py

經上述步驟, 會在根目錄產生幾個子目錄
1. build : 執行包裝程序時的一些暫存設定
2. dist : 這是最重要的一個目錄, 最終成品 .exe就在此處. 把這裏的 .exe檔 copy給別人, 就可以執行了, 而且對方不需安裝 Python解譯器.

OpenCv

如果有使用到 OpenCv套件的話,包裝會出現如下問題 : ImportError: OpenCV loader: missing configuration file: [‘config.py‘].

此時必需取得安裝 OpenCv 的路徑。請開啟一個測試檔,撰寫如下代碼

import cv2
print(cv2.__file__)
結果 :
D:\project\python\Projector\venv\lib\site-packages\cv2\__init__.py

然後將上述藍色部份,加入 –paths,如下所示

pyinstaller --hidden-import=queue -w -F Projector.py --paths="D:\project\python\Projector\venv\lib\site-packages\cv2"

打包圖片

底下是一般網路上的教法, 完全是錯誤的, 請不要用

1. pyi-makespec --hidden-import=queue -w -F DkLora.spec
2. 在mainFrame.spec加入
   a.datas+=(('lora.png','D:\\project\\python\\DkLora\\lora.png', 'DATA'),)
3. pyinstaller -F DkLora.spec

正確的方法, 請參照本站的 Pyinstall內崁圖片

Selenium Failed to execute script xxxxx

打包成exe檔時,使用 pyinstaller –hidden-import=queue -w -F xxx.py,其中的 -w 為不顯示 DOS 控制台。

但如果有裝 selenium時,因為會使用 DOS 視窗提示訊息,所以下達 -w 無效,還是會強迫產生控制台視窗。解決方式,必需修改selenium的原始碼,請開啟如下檔案

C:\Users\使用者\AppData\Local\Programs\Python\Python37\Lib\site-packages\selenium\webdriver\common\service.py

Python 3.7版增加下面藍色的部份即可解決

def start(self):
        """
        Starts the Service.

        :Exceptions:
         - WebDriverException : Raised either when it can't start the service
           or when it can't connect to the service
        """
        try:
            cmd = [self.path]
            cmd.extend(self.command_line_args())
            self.process = subprocess.Popen(cmd, env=self.env,
                                            close_fds=platform.system() != 'Windows',
                                            stdout=self.log_file, stderr=self.log_file
                                            ,stdin=PIPE,creationflags=134217728)
        except TypeError:
            raise

Python 3.8版增加下面藍色的部份即可解決

    def _start_process(self, path: str) -> None:
        """
        Creates a subprocess by executing the command provided.

        :param cmd: full command to execute
        """
        cmd = [path]
        cmd.extend(self.command_line_args())
        try:
            self.process = subprocess.Popen(
                cmd,
                env=self.env,
                close_fds=system() != "Windows",
                stdout=self.log_file,
                stderr=self.log_file,
                stdin=PIPE,
                #creationflags=self.creation_flags,
                creationflags=134217728,
            )
            logger.debug(f"Started executable: `{self.path}` in a child process with pid: {self.process.pid}")
        except TypeError:
            raise

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *