Web приложение на Python Flask/PySide6 в виде десктопной программы

GetCoder.ru
Изображение статьи

В этой статье мы рассмотрим вариант создания веб-приложения на Python Flask / PySide6 в качестве настольной программы для Windows. Библиотека Flask будет отвечать за обработку запросов, а PySide6 - за вывод полученной информации.

В этой статье мы рассмотрим вариант создания веб-приложения на Python Flask / PySide6 в качестве настольной программы для Windows. Библиотека Flask будет отвечать за обработку запросов, а PySide6 - за вывод полученной информации.

Как это работает

  • start: Основной скрипт, который запускает веб-службу и браузер через субпроцессы;
  • web_service: Веб-служба, работающая на Flask, обрабатывает запросы и предоставляет интерфейс;
  • browser: Интерфейсный модуль на PySide6, который использует встроенный браузер (QWebEngineView) для отображения сайта;
  • design: Директория, в которой находится структура сайта (HTML, CSS, JS);

Start

  • copy
#-*- coding: UTF-8 -*- import time, subprocess class Main(): def __init__(self): host = '127.0.0.1' port = '5000' try: web_service = subprocess.Popen(["python", "web_service.py", host, port]) browser = subprocess.Popen(["python", "browser.py", host, port]) while True: time.sleep(1) except KeyboardInterrupt: pass print("Основной процесс завершен. Завершаем субпроцесс.") web_service.terminate() browser.terminate() web_service.wait() browser.wait() print("Субпроцессы завершены.") if __name__ == "__main__": Main()

Browser

  • copy
#-*- coding: UTF-8 -*- import sys from PySide6.QtCore import QUrl from PySide6.QtWidgets import QApplication, QMainWindow from PySide6.QtWebEngineWidgets import QWebEngineView host = sys.argv[1] port = sys.argv[2] url = 'http://'+host+':'+port class Browser(): def __init__(self): app = QApplication(sys.argv) mw = QMainWindow() mw.setWindowTitle("WebApp") mw.setGeometry(100, 100, 800, 600) mw.browser = QWebEngineView() mw.browser.setUrl(QUrl(url)) mw.setCentralWidget(mw.browser) mw.show() sys.exit(app.exec()) if __name__ == "__main__": Browser()

Web_service

  • copy
#-*- coding: UTF-8 -*- from flask import Flask, request, Response import re, mimetypes, sys host = sys.argv[1] port = sys.argv[2] class webService: def __init__(self): self.app = Flask(__name__) # Получение запроса @self.app.route('/', defaults={'path': ''}) @self.app.route('/', methods=['GET', 'POST']) def route(path): answer = self.process_route() return Response(response = answer['response'], status = answer['status'], mimetype = answer['mimetype']) self.app.run(host=host, port=port, debug=True) # Определение mimeType def get_mime_type(self, file_path): mime_type, _ = mimetypes.guess_type(file_path) return mime_type # Изменение данных в строке с помощью replace через цикл def replace_str(self, strData, mData): for keyItem, dataItem in mData.items(): strData = strData.replace(keyItem, dataItem) return strData # Очистка параметров def clean_string(self, input_string): cleaned_string = re.sub(r'[^a-zA-Z0-9]', '', input_string) return cleaned_string # Обработка входящих параметров def proccess_params(self): result = {} try: urlRequest = request.url mParam = urlRequest.split('?') if len(mParam) > 1: mVar = mParam[1].split('&') for item in mVar: mItem = item.split('=') if mItem[0] == '' or len(mItem) == 1: continue result[self.clean_string(mItem[0])] = self.clean_string(mItem[1]) except Exception as e: print('proccess_params: '+str(e)) return result # Работа с шаблоном def process_template(self, path_file, typeRead = 'r'): try: if typeRead == 'rb': with open(path_file, typeRead) as f: result = f.read() else: with open(path_file, typeRead, encoding='utf-8') as f: result = f.read() except Exception as e: raise Exception('404') return result # Обработка запроса def process_route(self): result = {'status': 200, 'response': '', 'mimetype': 'text/html', 'typeRead': 'r'} try: server_host = str(request.scheme)+'://'+str(request.server[0])+':'+str(request.server[1]) request_data = {'method': request.method, 'path': request.view_args['path'].split('/'), 'variable': self.proccess_params()} if request_data['method'] == 'GET': if request_data['path'][0] == '': request_data['path'][0] = 'index.html' # Подгрузка страницы if len(request_data['path']) == 1: result['response'] = self.process_template('design/template/'+request_data['path'][0]) # Подгрузка дизайна elif request_data['path'][0] == 'design': result['mimetype'] = self.get_mime_type(request.view_args['path']) mMimetype = str(result['mimetype']).split('/') result['typeRead'] = 'rb' if mMimetype[0] == 'image' else 'r' result['response'] = self.process_template(request.view_args['path'], result['typeRead']) if result['response'] == False: raise Exception('404') else: raise Exception('404') else: raise Exception('404') except Exception as e: # Подгрузка 404 страницы result['response'] = self.process_template('design/template/404.html') result['status'] = 404 if result['typeRead'] != 'rb': mData = {'SERVER_HOST': server_host} result['response'] = self.replace_str(result['response'], mData) return result if __name__ == "__main__": webService()

Design

  • copy
project/ ├── start.py ├── browser.py ├── web_service.py ├── design/ │ ├── template/ │ └── css/ │ └── img/ │ └── js/

Для создания дополнительных страниц, достаточно в директорию design/template/ добавить html файл с названием страницы.

Запуск

Установите необходимые библиотеки:

  • copy
pip install flask PySide6

Запустите start.py

  • copy
python start.py

После запуска приложение откроется в виде окна, а внутри него будет отображаться веб-интерфейс, работающий на Flask.

Исходный код

Заключение

Мы создали десктопное приложение, которое использует Flask для обработки веб-запросов и PySide6 для отображения интерфейса в настольном окне. Эта архитектура позволяет легко разрабатывать приложения с гибкими веб-технологиями, обеспечивая десктопный интерфейс.

  • 27.12.2024
  • 129
  • 0

Web приложение на Python Flask/PySide6 в виде десктопной программы

В этой статье мы рассмотрим вариант создания веб-приложения на Python Flask / PySide6 в качестве настольной программы для Windows. Библиотека Flask будет отвечать за обработку запросов, а PySide6 - за вывод полученной информации.

Как это работает

  • start: Основной скрипт, который запускает веб-службу и браузер через субпроцессы;
  • web_service: Веб-служба, работающая на Flask, обрабатывает запросы и предоставляет интерфейс;
  • browser: Интерфейсный модуль на PySide6, который использует встроенный браузер (QWebEngineView) для отображения сайта;
  • design: Директория, в которой находится структура сайта (HTML, CSS, JS);

Start

  • copy
#-*- coding: UTF-8 -*- import time, subprocess class Main(): def __init__(self): host = '127.0.0.1' port = '5000' try: web_service = subprocess.Popen(["python", "web_service.py", host, port]) browser = subprocess.Popen(["python", "browser.py", host, port]) while True: time.sleep(1) except KeyboardInterrupt: pass print("Основной процесс завершен. Завершаем субпроцесс.") web_service.terminate() browser.terminate() web_service.wait() browser.wait() print("Субпроцессы завершены.") if __name__ == "__main__": Main()

Browser

  • copy
#-*- coding: UTF-8 -*- import sys from PySide6.QtCore import QUrl from PySide6.QtWidgets import QApplication, QMainWindow from PySide6.QtWebEngineWidgets import QWebEngineView host = sys.argv[1] port = sys.argv[2] url = 'http://'+host+':'+port class Browser(): def __init__(self): app = QApplication(sys.argv) mw = QMainWindow() mw.setWindowTitle("WebApp") mw.setGeometry(100, 100, 800, 600) mw.browser = QWebEngineView() mw.browser.setUrl(QUrl(url)) mw.setCentralWidget(mw.browser) mw.show() sys.exit(app.exec()) if __name__ == "__main__": Browser()

Web_service

  • copy
#-*- coding: UTF-8 -*- from flask import Flask, request, Response import re, mimetypes, sys host = sys.argv[1] port = sys.argv[2] class webService: def __init__(self): self.app = Flask(__name__) # Получение запроса @self.app.route('/', defaults={'path': ''}) @self.app.route('/', methods=['GET', 'POST']) def route(path): answer = self.process_route() return Response(response = answer['response'], status = answer['status'], mimetype = answer['mimetype']) self.app.run(host=host, port=port, debug=True) # Определение mimeType def get_mime_type(self, file_path): mime_type, _ = mimetypes.guess_type(file_path) return mime_type # Изменение данных в строке с помощью replace через цикл def replace_str(self, strData, mData): for keyItem, dataItem in mData.items(): strData = strData.replace(keyItem, dataItem) return strData # Очистка параметров def clean_string(self, input_string): cleaned_string = re.sub(r'[^a-zA-Z0-9]', '', input_string) return cleaned_string # Обработка входящих параметров def proccess_params(self): result = {} try: urlRequest = request.url mParam = urlRequest.split('?') if len(mParam) > 1: mVar = mParam[1].split('&') for item in mVar: mItem = item.split('=') if mItem[0] == '' or len(mItem) == 1: continue result[self.clean_string(mItem[0])] = self.clean_string(mItem[1]) except Exception as e: print('proccess_params: '+str(e)) return result # Работа с шаблоном def process_template(self, path_file, typeRead = 'r'): try: if typeRead == 'rb': with open(path_file, typeRead) as f: result = f.read() else: with open(path_file, typeRead, encoding='utf-8') as f: result = f.read() except Exception as e: raise Exception('404') return result # Обработка запроса def process_route(self): result = {'status': 200, 'response': '', 'mimetype': 'text/html', 'typeRead': 'r'} try: server_host = str(request.scheme)+'://'+str(request.server[0])+':'+str(request.server[1]) request_data = {'method': request.method, 'path': request.view_args['path'].split('/'), 'variable': self.proccess_params()} if request_data['method'] == 'GET': if request_data['path'][0] == '': request_data['path'][0] = 'index.html' # Подгрузка страницы if len(request_data['path']) == 1: result['response'] = self.process_template('design/template/'+request_data['path'][0]) # Подгрузка дизайна elif request_data['path'][0] == 'design': result['mimetype'] = self.get_mime_type(request.view_args['path']) mMimetype = str(result['mimetype']).split('/') result['typeRead'] = 'rb' if mMimetype[0] == 'image' else 'r' result['response'] = self.process_template(request.view_args['path'], result['typeRead']) if result['response'] == False: raise Exception('404') else: raise Exception('404') else: raise Exception('404') except Exception as e: # Подгрузка 404 страницы result['response'] = self.process_template('design/template/404.html') result['status'] = 404 if result['typeRead'] != 'rb': mData = {'SERVER_HOST': server_host} result['response'] = self.replace_str(result['response'], mData) return result if __name__ == "__main__": webService()

Design

  • copy
project/ ├── start.py ├── browser.py ├── web_service.py ├── design/ │ ├── template/ │ └── css/ │ └── img/ │ └── js/

Для создания дополнительных страниц, достаточно в директорию design/template/ добавить html файл с названием страницы.

Запуск

Установите необходимые библиотеки:

  • copy
pip install flask PySide6

Запустите start.py

  • copy
python start.py

После запуска приложение откроется в виде окна, а внутри него будет отображаться веб-интерфейс, работающий на Flask.

Исходный код

Заключение

Мы создали десктопное приложение, которое использует Flask для обработки веб-запросов и PySide6 для отображения интерфейса в настольном окне. Эта архитектура позволяет легко разрабатывать приложения с гибкими веб-технологиями, обеспечивая десктопный интерфейс.