PyQt: как реализовать самообновляемый исполняемый файл? - PullRequest
0 голосов
/ 22 марта 2019

Я пытаюсь реализовать кнопку «самообновления» в приложении PyQt5.Я создаю исполняемый файл с pyinstaller SelfUpdate.py --onefile.Если у меня будет новая скомпилированная версия моего приложения, я помещу ее в каталог загрузки в сети.Программа запускается разными пользователями на их ПК, и если кто-то нажимает кнопку обновления, его / ее приложение должно быть заменено новым.Я работаю над Win7 / 64, Python 3.6.3.

Я еще не нашел код Python для этого, но здесь Я нашел описание, которое я адаптировал:

  1. скопировать новый .exe из каталога обновлений в локальный .ex_
  2. удалить старый .bak, если он существует
  3. переименовать запущенную программу .exe в .bak
  4. переименоватьновая программа .ex_ в .exe
  5. запустить обновленную программу .exe как самостоятельный процесс
  6. выйти из запущенной в данный момент устаревшей программы

Мой минимальный пример кода следующий.В конце концов, другие файлы и каталоги также должны быть заменены.Кажется, он работает и в основном делает то, что я хочу, однако я хотел бы знать: это путь или есть, возможно, более простые / умные / лучшие способы достижения такой кнопки самообновления?

import sys,shutil,os,time
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox 
import subprocess
from datetime import datetime

class MyWindow(QWidget):
    def __init__(self):
        super(MyWindow,self).__init__()
        self.setWindowTitle('Self updating pogram')
        self.setGeometry(100,100,200,100)
        self.pb_update = QPushButton('Check for updates',self)
        self.pb_update.move(50,20)
        self.pb_update.clicked.connect(self.pb_update_clicked)

    def pb_update_clicked(self):
        dir_download = r'C:\User\Code\NewestVersion'
        fname = "SelfUpdate.exe"
        ffname_update = os.path.join(dir_download,fname)
        time_update = os.path.getmtime(ffname_update)
        time_current = os.path.getmtime(fname)
        print(ffname_update, "\n", datetime.fromtimestamp(time_update).isoformat())
        print(fname, "\n", datetime.fromtimestamp(time_current).isoformat())
        if (time_update > time_current):
            title = "Check for updates"
            message = "Do you want to update?"
            response = QMessageBox.question(self, title, message, QMessageBox.Yes | QMessageBox.No)
            if response == QMessageBox.Yes:
                print("File will be updated. Please wait...")
                shutil.copy2(ffname_update,fname[:-4]+'.ex_') # copy new file to .ex_
                if os.path.isfile(fname[:-4]+'.bak'):
                    os.remove(fname[:-4]+'.bak')              # remove previous .bak
                os.rename(fname,fname[:-4]+'.bak')            # rename running programm to .bak
                os.rename(fname[:-4]+'.ex_',fname)            # rename new program .ex_ to .exe
                subprocess.Popen([fname],close_fds=True)      # start updated program as independent process
                sys.exit()                                    # exit old program
        else:
            print("No update available.")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle("plastique")
    window = MyWindow()
    window.show()
    sys.exit(app.exec_())
...