1. 程式人生 > >《快速掌握PyQt5》第二十二章 Pyinstaller打包

《快速掌握PyQt5》第二十二章 Pyinstaller打包

第二十二章 Pyinstaller打包

寫完的程式如果要發給別人使用,但對方並沒有安裝python環境,也沒有安裝PyQt5庫時怎麼辦呢?最好的解決辦法就是將程式打包成可執行檔案,這樣就算在一臺沒有安裝python環境和PyQt5庫的電腦上也可以使用,非常方便。

22.1 下載Pyinstaller

windows上下載:

pip install pyinstaller

Linux上下載:

pip3 install pyinstaller

Mac上下載:

pip3 install pyinstaller

下載完後我們開啟終端,輸入pyinstaller,若顯示如下,則表示安裝成功:

22.2 瞭解Pyinstaller命令引數

這裡我們只需要瞭解幾個常用命令即可,詳細用法請參考Pyinstaller手冊

引數 用處
-F 將程式打包成一個檔案
-w 去除黑框
-i 新增程式圖示

22.3 打包示例

我們就將第五章的登入框小程式拿過來打包作為示例好了,該程式的程式碼如下:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QDialog, QLabel, QLineEdit, QPushButton, \
    QGridLayout, QVBoxLayout, QHBoxLayout, QMessageBox

USER_PWD = {
        'la_vie': 'password'
    }


class Demo(QWidget):
    def __init__(self):
        super(Demo, self).__init__()
        self.resize(300, 100)

        self.user_label = QLabel('Username:', self)
        self.pwd_label = QLabel('Password:', self)
        self.user_line = QLineEdit(self)
        self.pwd_line = QLineEdit(self)
        self.login_button = QPushButton('Log in', self)
        self.signin_button = QPushButton('Sign in', self)

        self.grid_layout = QGridLayout()
        self.h_layout = QHBoxLayout()
        self.v_layout = QVBoxLayout()

        self.lineedit_init()
        self.pushbutton_init()
        self.layout_init()
        self.signin_page = SigninPage()     # 例項化SigninPage()

    def layout_init(self):
        self.grid_layout.addWidget(self.user_label, 0, 0, 1, 1)
        self.grid_layout.addWidget(self.user_line, 0, 1, 1, 1)
        self.grid_layout.addWidget(self.pwd_label, 1, 0, 1, 1)
        self.grid_layout.addWidget(self.pwd_line, 1, 1, 1, 1)
        self.h_layout.addWidget(self.login_button)
        self.h_layout.addWidget(self.signin_button)
        self.v_layout.addLayout(self.grid_layout)
        self.v_layout.addLayout(self.h_layout)

        self.setLayout(self.v_layout)

    def lineedit_init(self):
        self.user_line.setPlaceholderText('Please enter your username')
        self.pwd_line.setPlaceholderText('Please enter your password')
        self.pwd_line.setEchoMode(QLineEdit.Password)

        self.user_line.textChanged.connect(self.check_input_func)
        self.pwd_line.textChanged.connect(self.check_input_func)

    def pushbutton_init(self):
        self.login_button.setEnabled(False)
        self.login_button.clicked.connect(self.check_login_func)
        self.signin_button.clicked.connect(self.show_signin_page_func)

    def check_login_func(self):
        if USER_PWD.get(self.user_line.text()) == self.pwd_line.text():
            QMessageBox.information(self, 'Information', 'Log in Successfully!')
        else:
            QMessageBox.critical(self, 'Wrong', 'Wrong Username or Password!')

        self.user_line.clear()
        self.pwd_line.clear()

    def show_signin_page_func(self):
        self.signin_page.exec_()

    def check_input_func(self):
        if self.user_line.text() and self.pwd_line.text():
            self.login_button.setEnabled(True)
        else:
            self.login_button.setEnabled(False)


class SigninPage(QDialog):
    def __init__(self):
        super(SigninPage, self).__init__()
        self.signin_user_label = QLabel('Username:')
        self.signin_pwd_label = QLabel('Password:')
        self.signin_pwd2_label = QLabel('Password:')
        self.signin_user_line = QLineEdit()
        self.signin_pwd_line = QLineEdit()
        self.signin_pwd2_line = QLineEdit()
        self.signin_button = QPushButton('Sign in')

        self.user_h_layout = QHBoxLayout()
        self.pwd_h_layout = QHBoxLayout()
        self.pwd2_h_layout = QHBoxLayout()
        self.all_v_layout = QVBoxLayout()

        self.lineedit_init()
        self.pushbutton_init()
        self.layout_init()

    def layout_init(self):
        self.user_h_layout.addWidget(self.signin_user_label)
        self.user_h_layout.addWidget(self.signin_user_line)
        self.pwd_h_layout.addWidget(self.signin_pwd_label)
        self.pwd_h_layout.addWidget(self.signin_pwd_line)
        self.pwd2_h_layout.addWidget(self.signin_pwd2_label)
        self.pwd2_h_layout.addWidget(self.signin_pwd2_line)

        self.all_v_layout.addLayout(self.user_h_layout)
        self.all_v_layout.addLayout(self.pwd_h_layout)
        self.all_v_layout.addLayout(self.pwd2_h_layout)
        self.all_v_layout.addWidget(self.signin_button)

        self.setLayout(self.all_v_layout)

    def lineedit_init(self):
        self.signin_pwd_line.setEchoMode(QLineEdit.Password)
        self.signin_pwd2_line.setEchoMode(QLineEdit.Password)

        self.signin_user_line.textChanged.connect(self.check_input_func)
        self.signin_pwd_line.textChanged.connect(self.check_input_func)
        self.signin_pwd2_line.textChanged.connect(self.check_input_func)

    def pushbutton_init(self):
        self.signin_button.setEnabled(False)
        self.signin_button.clicked.connect(self.check_signin_func)

    def check_input_func(self):
        if self.signin_user_line.text() and self.signin_pwd_line.text() and self.signin_pwd2_line.text():
            self.signin_button.setEnabled(True)
        else:
            self.signin_button.setEnabled(False)

    def check_signin_func(self):
        if self.signin_pwd_line.text() != self.signin_pwd2_line.text():
            QMessageBox.critical(self, 'Wrong', 'Two Passwords Typed Are Not Same!')
        elif self.signin_user_line.text() not in USER_PWD:
            USER_PWD[self.signin_user_line.text()] = self.signin_pwd_line.text()
            QMessageBox.information(self, 'Information', 'Register Successfully')
            self.close()
        else:
            QMessageBox.critical(self, 'Wrong', 'This Username Has Been Registered!')

        self.signin_user_line.clear()
        self.signin_pwd_line.clear()
        self.signin_pwd2_line.clear()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

我們將這個py檔案命名為test.py,並將檔案放到桌面上,之後開啟命令列視窗,cd到桌面目錄,輸入pyinstaller -F -w test.py

點選回車,開始打包:

結束後我們會發現在桌面上多了兩個資料夾和一個spec檔案:

而我們想要的可執行程式就在dist資料夾中,雙擊開啟就是我們的程式了:

 

現在你完全可以就將這個test可執行檔案放到其他電腦上去執行。

上面打包的可執行檔案使用的是預設的圖示,我們接下來打包時新增-i引數來給程式加個圖示(請注意該用法只對Windows系統有效):

將該圖示命名為login.ico並放在桌面,跟test.py同路徑。同樣開啟命令列視窗,cd到桌面,輸入pyinstaller -F -w -i login.ico test.py 按回車開始打包:

然後在dist資料夾中就可以找到我們打包好的可執行檔案:

22.4 小結

1. 打包時可能會出現各種各樣的問題,但大部分問題其實只要仔細閱讀報錯內容就可以解決,不要慌;

2. 筆者彙總了一些用Pyinstaller打包時出現的問題,詳情請見:Pyinstaller打包問題之解決方案彙總

----------------------------------------------------------------------

喜歡的小夥伴可以加入這個Python QQ交流群一起學習:820934083