Как собрать в ехе код python без отображения консоли?
флаг F я бы не рекомендовал. выглядит красиво но замедляет запуск вашей программы если она будет увесистая. видимо лишнее время на распаковку этого добра уходит.
5 окт в 7:08
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.11.15.1019
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Десктопное приложение на Python: UI и сигналы
С помощью Python можно создавать современные десктопные приложения. Рассказываем, как сделать графический интерфейс с помощью кода.
Считается, что Python не лучший выбор для десктопных приложений. Однако, когда в 2016 году я собирался переходить от разработки сайтов к программному обеспечению, Google подсказал мне, что на Python можно создавать сложные современные приложения. Например blender3d, который написан на Python.
Но люди, не по своей вине используют уродливые примеры графического интерфейса, которые выглядят слишком старыми, и не понравятся молодёжи. Я надеюсь изменить это мнение в своем туториале. Давайте начнём.
Мы будем использовать PyQt (произносится «Пай-Кьют»). Это фреймворк Qt, портированный с C++. Qt известен тем, что необходим C++ разработчикам. С помощью этого фреймворка сделаны blender3d, Tableau, Telegram, Anaconda Navigator, Ipython, Jupyter Notebook, VirtualBox, VLC и другие. Мы будем использовать его вместо удручающего Tkinter.
Требования
- Вы должны знать основы Python
- Вы должны знать, как устанавливать пакеты и библиотеки с помощью pip.
- У вас должен быть установлен Python.
Установка
Вам нужно установить только PyQt. Откройте терминал и введите команду:
>>> pip install PyQt5
Мы будем использовать PyQt версии 5.15. Дождитесь окончания установки, это займёт пару минут.
Hello, World!
Создайте папку с проектом, мы назовём его helloApp. Откройте файл main.py, лучше сделать это vscode, и введите следующий код:
import sys from PyQt5.QtGui import QGuiApplication from PyQt5.QtQml import QQmlApplicationEngine app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() engine.quit.connect(app.quit) engine.load('./UI/main.qml') sys.exit(app.exec())
Этот код вызывает QGuiApplication и QQmlApplicationEngine которые используют Qml вместо QtWidget в качестве UI слоя в Qt приложении. Затем, мы присоединяем UI функцию выхода к главной функции выхода приложения. Теперь они оба закроются одновременно, когда пользователь нажмёт выход. Затем, загружаем qml файл для Qml UI. Вызов app.exec(), запускает приложение, он находится внутри sys.exit, потому что возвращает код выхода, который передается в sys.exit.
Добавьте этот код в main.qml:
import QtQuick 2.15 import QtQuick.Controls 2.15 ApplicationWindow < visible: true width: 600 height: 500 title: "HelloApp" Text < anchors.centerIn: parent text: "Hello, World" font.pixelSize: 24 >>
Этот код создает окно, делает его видимым, с указанными размерами и заголовком. Объект Text отображается в середине окна.
Теперь давайте запустим приложение:
>>> python main.py
Вы увидите такое окно:
Обновление UI
Давайте немного обновим UI, добавим фоновое изображение и время:
import QtQuick 2.15 import QtQuick.Controls 2.15 ApplicationWindow < visible: true width: 400 height: 600 title: "HelloApp" Rectangle < anchors.fill: parent Image < sourceSize.width: parent.width sourceSize.height: parent.height source: "./images/playas.jpg" fillMode: Image.PreserveAspectCrop >Rectangle < anchors.fill: parent color: "transparent" Text < text: "16:38:33" font.pixelSize: 24 color: "white" >> > >
Внутри типа ApplicationWindow находится содержимое окна, тип Rectangle заполняет пространство окна. Внутри него находится тип Image и другой прозрачный Rectangle который отобразится поверх изображения.
Если сейчас запустить приложение, то текст появится в левом верхнем углу. Но нам нужен левый нижний угол, поэтому используем отступы:
Text < anchors < bottom: parent.bottom bottomMargin: 12 left: parent.left leftMargin: 12 >text: "16:38:33" font.pixelSize: 24 . >
После запуска вы увидите следующее:
Показываем текущее время
Модуль gmtime позволяет использовать структуру со временем, а strftime даёт возможность преобразовать её в строку. Импортируем их:
import sys from time import strftime, gmtime
Теперь мы можем получить строку с текущим временем:
curr_time = strftime("%H:%M:%S", gmtime())
Строка «%H:%M:%S» означает, что мы получим время в 24 часовом формате, с часами минутами и секундами (подробнее о strtime).
Давайте создадим property в qml файле, для хранения времени. Мы назовём его currTime.
property string currTime: "00:00:00"
Теперь заменим текст нашей переменной:
Text < . text: currTime // used to be; text: "16:38:33" font.pixelSize: 48 color: "white" >
Теперь, передадим переменную curr_time из pyhton в qml:
engine.load('./UI/main.qml') engine.rootObjects()[0].setProperty('currTime', curr_time)
Это один из способов передачи информации из Python в UI.
Запустите приложение и вы увидите текущее время.
Обновление времени
Для того чтобы обновлять время, нам нужно использовать потоки. Для этого я предлагаю использовать сигналы.
Чтобы использовать сигналы нам нужен подкласс QObject. Назовём его Backend.
. from PyQt5.QtCore import QObject, pyqtSignal class Backend(QObject): def __init__(self): QObject.__init__(self) .
У нас уже имеется свойства для строки со временем curr_time, теперь создадим свойство backend типа QtObject в файле main.qml.
property string currTime: "00:00:00" property QtObject backend
Передадим данные из Python в qml:
engine.load('./UI/main.qml') back_end = Backend() engine.rootObjects()[0].setProperty('backend', back_end)
В qml файле один объект QtObject может получать несколько функций (называемых сигналами) из Python.
Создадим тип Connections и укажем backend в его target. Теперь внутри этого типа может быть столько функций, сколько нам необходимо получить в backend.
. Rectangle < anchors.fill: parent Image < . >. > Connections < target: backend >.
Таким образом мы свяжем qml и сигналы из Python.
Мы используем потоки, для того чтобы обеспечить своевременное обновление UI. Создадим две функции, одну для управления потоками, а вторую для выполнения действий. Хорошая практика использовать в названии одной из функций _.
. import threading from time import sleep . class Backend(QObject): def __init__(self): QObject.__init__(self) def bootUp(self): t_thread = threading.Thread(target=self._bootUp) t_thread.daemon = True t_thread.start() def _bootUp(self): while True: curr_time = strftime("%H:%M:%S", gmtime()) print(curr_time) sleep(1) .
Создадим pyqtsignal и назовём его updated, затем вызовем его из функции updater.
. from PyQt5.QtCore import QObject, pyqtSignal . def __init__(self): QObject.__init__(self) updated = pyqtSignal(str, arguments=['updater']) def updater(self, curr_time): self.updated.emit(curr_time) .
В этом коде updated имеет параметр arguments, который является списком, содержащим имя функции “updater”. Qml будет получать данные из этой функции. В функции updater мы вызываем метод emit и передаём ему данные о времени.
Обновим qml, получив сигнал, с помощью обработчика, название которого состоит из “on” и имени сигнала:
target: backend function onUpdated(msg)
Теперь нам осталось вызвать функцию updater. В нашем небольшом приложении, использовать отдельную функцию для вызова сигнала не обязательно. Но это рекомендуется делать в больших программах. Изменим задержку на одну десятую секунды.
curr_time = strftime("%H:%M:%S", gmtime()) self.updater(curr_time) sleep(0.1)
Функция bootUp должна быть вызвана сразу же после загрузки UI:
engine.rootObjects()[0].setProperty('backend', back_end) back_end.bootUp() sys.exit(app.exec())
Всё готово
Теперь можно запустить программу. Время будет обновляться корректно. Для того, чтобы убрать рамку, вы можете добавить в qml файл следующую строку:
flags: Qt.FramelessWindowHint | Qt.Window
Так должен выглядеть файл main.py:
import sys from time import strftime, gmtime import threading from time import sleep from PyQt5.QtGui import QGuiApplication from PyQt5.QtQml import QQmlApplicationEngine from PyQt5.QtCore import QObject, pyqtSignal class Backend(QObject): def __init__(self): QObject.__init__(self) updated = pyqtSignal(str, arguments=['updater']) def updater(self, curr_time): self.updated.emit(curr_time) def bootUp(self): t_thread = threading.Thread(target=self._bootUp) t_thread.daemon = True t_thread.start() def _bootUp(self): while True: curr_time = strftime("%H:%M:%S", gmtime()) self.updater(curr_time) sleep(0.1) app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() engine.quit.connect(app.quit) engine.load('./UI/main.qml') back_end = Backend() engine.rootObjects()[0].setProperty('backend', back_end) back_end.bootUp() sys.exit(app.exec())
Вот содержимое файла main.qml:
import QtQuick 2.15 import QtQuick.Controls 2.15 ApplicationWindow < visible: true width: 360 height: 600 x: screen.desktopAvailableWidth - width - 12 y: screen.desktopAvailableHeight - height - 48 title: "HelloApp" flags: Qt.FramelessWindowHint | Qt.Window property string currTime: "00:00:00" property QtObject backend Rectangle < anchors.fill: parent Image < sourceSize.width: parent.width sourceSize.height: parent.height source: "./images/playas.jpg" fillMode: Image.PreserveAspectFit >Text < anchors < bottom: parent.bottom bottomMargin: 12 left: parent.left leftMargin: 12 >text: currTime font.pixelSize: 48 color: "white" > > Connections < target: backend function onUpdated(msg) < currTime = msg; >> >
Сборка приложения
Для сборки десктопного приложения на Python нам понадобится pyinstaller.
>>> pip install pyinstaller
Чтобы в сборку добавились все необходимые ресурсы, создадим файл spec:
>>> pyi-makespec main.py
Настройки файла spec
Параметр datas можно использовать для того, чтобы включить файл в приложение. Это список кортежей, каждый из которых обязательно должен иметь target path(откуда брать файлы) и destination path(где будет находится приложение). destination path должен быть относительным. Чтобы расположить все ресурсы в одной папке с exe-файлами используйте пустую строку.
Измените параметр datas, на путь к вашей папке с UI:
a = Analysis(['main.py'], . datas=[('I:/path/to/helloApp/UI', 'UI')], hiddenimports=[], . exe = EXE(pyz, a.scripts, [], . name='main', debug=False, . console=False ) coll = COLLECT(exe, . upx_exclude=[], name='main')
Параметр console установим в false, потому что у нас не консольное приложение.
Параметр name внутри вызова Exe, это имя исполняемого файла. name внутри вызова Collect, это имя папки в которой появится готовое приложение. Имена создаются на основании файла для которого мы создали spec — main.py.
Теперь можно запустить сборку:
>>> pyinstaller main.spec
В папке dist появится папка main. Для запуска программы достаточно запустить файл main.exe.
Так будет выглядеть содержимое папки с десктопным приложением на Python:
О том, как использовать Qt Designer для создания UI приложений на Python читайте в нашей статье.
Как сделать графический интерфейс для .bat?
Python\python.exe dvbl_pckDir.py
del /f /q %dvpl_convert%\dvpl_convert\pack\*.*
Python\python.exe dvbl_renaming_in.py
copy %dvpl_convert%\dvpl_convert\temp\ %dvpl_convert%\dvpl_convert\pack\
del /f /q %dvpl_convert%\dvpl_convert\temp\*.*
@pause
Хотелось бы хоть немного графики, просто на уровне вставки картинок наверх красивого окна и появления кнопки «Завершено»
Голосование за лучший ответ
Забить на этот bat и написать все это счастье на чем-то, что поддерживает графику, например C#/WinForms или Delphi/VCL.
ну разве что переписав консоль.
Παν μέτρον άριστονМыслитель (9566) 3 года назад
Я не понимаю виндусоидов, почему они до сих пор пользуются bat (CMD), если давно появился PowerShell.
How to Convert Any Python File to .exe? | GeeksforGeeks
In this video, we’re going to discuss how to convert a Python (.py) file to a .exe file. When you convert a Python file to a .exe file, it basically allows the other individuals to run your Python script without actually installing Python on their respective systems. Here, we’ll see two ways to do this particular thing — one is via using the pyinstaller library and another is via using auto-py-to-exe library. So, let’s get started now. Check Out the Related Articles: Convert Python Script to .exe File [ https://www.geeksforgeeks.org/convert-python-script-to-exe-file/ ] Complete Python Tutorial [ https://www.geeksforgeeks.org/python-programming-language/ ] Apply For Video Internship Program — https://script.geeksforgeeks.org/on-boarding/youtube Our courses: https://practice.geeksforgeeks.org/courses/ This video is contributed by Shambhavi Gupta. Please Like, Comment, and Share the Video with your friends. #python #exefile #geeksforgeeks #howto #projects #beginner #cmd Install our Android App: https://play.google.com/store/apps/details?id=free.programming.programming&hl=en If you wish, translate into the local language and help us reach millions of other geeks: http://www.youtube.com/timedtext_cs_panel?c=UC0RhatS1pyxInC00YKjjBqQ&tab=2 Follow us on our Social Media Handles — Twitter- https://twitter.com/geeksforgeeks LinkedIn- https://www.linkedin.com/company/geeksforgeeks Facebook- https://www.facebook.com/geeksforgeeks.org Instagram- https://www.instagram.com/geeks_for_geeks/?hl=en Reddit- https://www.reddit.com/user/geeksforgeeks Telegram- https://t.me/s/geeksforgeeks_official Also, Subscribe if you haven’t already! 🙂
Показать больше
Войдите , чтобы оставлять комментарии.
