Я хочу создать механизм автоматического обновления для моего приложения PyQt PyInstaller.
Моя программа загружает установщик (Inno Setup ) с сервера, запускает его, а затем сразу закрывается. Затем установщик устанавливает новую версию моей программы, после чего она должна запуститься автоматически. Однако вместо запуска моя программа выдает ошибку «Не удалось загрузить Python DLL 'C:\Users\user\AppData\Local\Temp_MEI278082\python3.10.dll.'».
По какой-то причине Pyinstaller exe пытается получить доступ к временным файлам, которые были удалены после закрытия первой версии моего приложения.
Приведу пример:
[*]myProg.exe запускается и создает временную папку «_MEI123».
[*]myProg закрывается, а папка «_MEI123» удаляется.[*]Установщик заменяет myProg новой версией
[*]При запуске myProg он пытается получить доступ к '_MEI123', которого больше не существует
< /ul>
Важно отметить, что если вы запускаете приложение вручную, ошибок при запуске не возникает. Если вы запустите установщик вручную, моя программа также запустится автоматически после установки без ошибок.
Я пробовал запустить приложение после установки, используя команды Inno (запуск после установки) и CMD:
р>
Код: Выделить всё
subprocess.Popen(['cmd.exe', '/c', fr'{installer_path} /silent && {exe_path}'], creationflags=0x00000008 | 0x00000200)
Если вы вручную вызываете команду через консоль:
Код: Выделить всё
start /wait "C:\Users\user\myProg_setup.exe" /silent && "C:\Users\user\myProg.exe" То есть почему-то причина этой ошибки в том, что установщик моего приложения был началось с моего собственного приложения. Пока что единственное решение, которое сработало, — это установить файл с другим именем. Однако этот вариант для меня не идеален.
РЕДАКТИРОВАТЬ:
Минимально воспроизводимый пример:main.py
Код: Выделить всё
import subprocess
import sys
from PyQt5.QtWidgets import QApplication, QPushButton
def update(): #path to same exe
subprocess.Popen(["cmd.exe", "/c", r"timeout /t 2 && C:\pytest\dist\main.exe"], creationflags=0x00000008 | 0x00000200, close_fds = True)
app.quit()
app = QApplication(sys.argv)
button = QPushButton('Click me!')
button.clicked.connect(update)
button.show()
sys.exit(app.exec_())
Код: Выделить всё
pyinstaller .\main.py --onefile --noconsoleВременные файлы, о которых я упомянул, — это интерпретатор Python, который создается PyInstaller неявно при запуске исполняемого файла.
Обновление исполняемого файла, как я выяснил, похоже, не играет существенной роли, поэтому я оставил только отложенный запуск исполняемого файла. та же программа.
Фактически, даже с флагами функция Popen все равно не может создать полностью изолированный экземпляр от родительского процесса. Экземпляр моей программы, работающий в Popen, считает, что родительский экземпляр программы все еще активен, поэтому он пытается получить доступ к интерпретатору родительской программы. Однако на этом этапе переводчик уже закрыт. Это всего лишь моя гипотеза, и я могу ошибаться.
Подробнее здесь: https://stackoverflow.com/questions/790 ... n-updating