Изучаем формат .pyw в python + примеры и объяснения кода

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0
Автор network work
Источник https://xss.is



Всем здравствуйте я решил создать статью где подробно опишу что такое формат .pyw в питоне , для чего был создан и как с ним работать . Одной статьей тут не обойтись , в этой статьей мы разберем базовые навыки .Присаживайтесь по удобнее а мы начинаем

Формат .pyw был создан разработчикам Гвидо ван Россум (создатель самого языка ).Цель данного формата было возможность создавать графические приложения на Windows .Данный формат славиться тем что позволяет запускать Python скрипты без консольного окна , что является большим плюсом для GUI

Давайте сравним обычный формат .py и формат .pyw .

Формат .pyw - формат идеально подходит для верстки графических приложений, запускается программы с данным форматом без надобности открывать консоль. Но есть нюанс , данный формат подходит для юзеров но для разрабов думаю по лучше будет сток формат .py , почему же ? Дело в том то что приложение с таким форматом запускается без консоли , значит и ошибки при написание мы не сможем видеть .Это проблема не такая большая , потому что можно запустить формат этот как и через консоль так и напрямую .В целом формат хороший и b и вполне подходит для верстки GUI.

Формат .py - Данный формат подходит буквально под все все типы приложений , включая консольные и графические. Данный формат запускается через консоль что делает для пользователя является минусом , все таки формат .pyw выглядит более профессионально и если можно так назвать белее . Можно сказать этот формат больше является жирным плюсом для разработчика чем для юзера

Вывод - оба форматы хороши по своему , что .py что .pyw но формат .py .Но формат .pyw выглядит как по мне более профессионально чем .py .Подробнее можете почитать в интернете( основную цель форматом думаю я рассказал )

Давайте разберем пару скриптов с этим форматом , начнем с самого легкого , закончим все это более сложным скриптом и заключением .

Первый скрипт у нас будет простой калькулятор , с простым но приятным дизайном . Давайте начнем

Python: Скопировать в буфер обмена
Код:
import tkinter as tk
from tkinter import messagebox

class Calculator:
    def __init__(self, root):
        self.root = root
        self.root.title("Калькулятор")

        self.display = tk.Entry(root, font=("Arial", 19), bd=13, relief=tk.SUNKEN, justify='right')
        self.display.grid(row=0, column=0, columnspan=4)

        buttons = [
            '1', '2', '3', '/',
            '4', '5', '6', '*',
            '7', '8', '9', '-',
            'C', '0', '=', '+' 
        ]
        row1 = 1
        row2 = 0
        for button in buttons:
            self.create_button(button, row1, row2)
            row2 += 1
            if row2 > 3:
                row2 = 0
                row1 += 1

    def create_button(self, text, row, column):
        button = tk.Button(self.root, text=text, padx=23, pady=23, font=("Arial", 16), command=lambda: self.on_button_click(text))
        button.grid(row=row, column=column, sticky='nsew')

    def on_button_click(self, text):
        if text == 'C':
            self.display.delete(0, tk.END)
        elif text == '=':
            try:
                # Разрешение дробей
                expression = self.display.get()
                result = eval(expression)
                self.display.delete(0, tk.END)
                self.display.insert(tk.END, str(result))
            except Exception as e:
                messagebox.showerror("Ошибка", "Ошибка вычисления")
                self.display.delete(0, tk.END)
        else:
            self.display.insert(tk.END, text)

if __name__ == "__main__":
    root = tk.Tk()
    calculator = Calculator(root)
    root.mainloop()

Давайте разберем каждую строчку данного скрипта

Python: Скопировать в буфер обмена
import tkinter as tk
- Импортируем модуль Tkinter и в добавок присваиваем ему можно сказать имя tk , для удобной работы .Что за библиотека Tkinter и зачем она нужна? Все просто , это стандартная библиотека python которая отвечает за создание графических интерфейсов

Python: Скопировать в буфер обмена
from tkinter import messagebox
- Импортируем модуль messagebox из Tkinter которая отвечает за показ всплывающих окон сообщений .В данном скрипте мы будем через нее показывать ошибки

Python: Скопировать в буфер обмена
class Calculator:
- Определяем новый класс Calculator , которая будет отвечать за содержания логики и интерфейс в данном случаи в калькуляторе

Python: Скопировать в буфер обмена
def __init__(self, root):
- можно сказать это конструктор класса , вызываемый при создании нового объекта , а так же принимает параметр root который отвечает за представления главного окна

Python: Скопировать в буфер обмена
self.root = root
- строчка сохраняет ссылку на главное окно для возможности использования в других методах

Python: Скопировать в буфер обмена
self.root.title("Калькулятор")
- Устанавливаем заголовок окна

Python: Скопировать в буфер обмена
self.display = tk.Entry(root, font=("Arial", 19), bd=13, relief=tk.SUNKEN, justify='right')
- строчка создает виджет entry , который используется для ввода и отображения текста , давайте разберем строчку подробнее .font=("Arial", 19) - устанавливаем шрифт Arial , размер шрифта будет 19 .bd=13 - установка ширины границы .relief=tk.SUNKEN - отвечает за границу виджета , можно сказать это идет как декорация .кнопки будут более реалистичными что делает калькулятор более приятным.justify='right - строчка отвечает за выравнивание текста по правому краю , мы будем вводить все цифры с правой стороны .Что как по мне удобно и опять же реалистично

Python: Скопировать в буфер обмена
self.display.grid(row=0, column=0, columnspan=4) - Так же размещает виджет entry, row=0
- установка виджета в первой строчке ,column=0 - установка виджета в первом столбце , columnspan=4 - строчка устанавливает виджет так , чтобы он занимал четыре столбца

Python: Скопировать в буфер обмена
Код:
    buttons = [
            '1', '2', '3', '/',
            '4', '5', '6', '*',
            '7', '8', '9', '-',
            'C', '0', '=', '+'
        ]
- Мы создали список с числами для кнопок в нашем калькуляторе .

Python: Скопировать в буфер обмена
row1 = 1
- инициализируем переменную для позиций кнопок , row 1 указывает на строку

Python: Скопировать в буфер обмена
row2 = 0
- все тоже самое что было сказано в row 1 но row 2 уже отвечает за указание столбца

Python: Скопировать в буфер обмена
for button in buttons:
- мы создаем можно сказать цикл для перебора каждой кнопки в выше созданном списке (buttons)

Python: Скопировать в буфер обмена
self.create_button(button, row1, row2)
- Строчка создает кнопки и размещает ее в указной нами строчке и столбце

Python: Скопировать в буфер обмена
row2 += 1
- переход к следующими столбцу

Python: Скопировать в буфер обмена
if row2 > 3:
- строка проверяет если столбец превышает 3 (уже последний столбец в сетке )

Python: Скопировать в буфер обмена
row2 = 0 , row1 += 1
- сбрасывает row2 в 0 и переходит к row1

Python: Скопировать в буфер обмена
def create_button(self, text, row, column)
- Используем метод для создания и размещение кнопок

Python: Скопировать в буфер обмена
button = tk.Button(self.root, text=text, padx=23, pady=23, font=("Arial", 16), command=lambda: self.on_button_click(text))
- для начало мы создаем кнопку с указанными параметрами , давайте эти параметры разберем .text=text - отвечает за текст в нашем случаи числа на кнопке .padx=23 - установка внутреннего отступа по горизонтали .pady=23 - установка внутреннего отступа по вертикали. font=("Arial", 16) - устанавливаем шрифт Arial и размер текста.command=lambda: self.on_button_click(text) - строчка отвечает за вызывание кнопки при нажатие на нее . А так же мы использовали lambda чтобы передать текст кнопки в метод "on_button_click"

Python: Скопировать в буфер обмена
button.grid(row=row, column=column, sticky='nsew')
- Размещаем кнопку в указанной нами строке и столбце .А sticky='nsew' можно сказать заставляет кнопку растягиваться по всей ячейки сетки ( очередной декор , который делает калькулятор приятным для глаза)

Сейчас мы разберем метод обработки нажатий кнопок в калькуляторе

Python: Скопировать в буфер обмена
def on_button_click(self, text)
- это метод для обработки нажатий на кнопки в калькуляторе

Python: Скопировать в буфер обмена
if text == 'C'
- строчка отвечает за грамотную работу кнопки C (очистка строчки )

Python: Скопировать в буфер обмена
self.display.delete(0, tk.END)
- строчка работает при нажатии на C ,она удаляет весь текст из поля ввода

Python: Скопировать в буфер обмена
elif text == '=':
- отвечает за выполнение вычисление

Python: Скопировать в буфер обмена
expression = self.display.get()
- строчка получает текст из поля ввода

Python: Скопировать в буфер обмена
result = eval(expression)
- вычисляет результат выражения , используя функцию eval() ( спойлер : к этой функции мы еще вернемся в других статьях)

Python: Скопировать в буфер обмена
self.display.delete(0, tk.END)
- строчка отвечает за очистку поле ввода

Python: Скопировать в буфер обмена
self.display.insert(tk.END, str(result)) -
выводим результат готового вычисления в поле ввода

Python: Скопировать в буфер обмена
except Exception as e:
Если возникнет какая то ошибка ( к примеру из за не правильного ввода ) , то строчка покажет сообщение об ошибке

Python: Скопировать в буфер обмена
messagebox.showerror("Ошибка", "Ошибка вычисления")
- выводим на экран пользователя сообщение об ошибке

Python: Скопировать в буфер обмена
self.display.delete(0, tk.END)
- очищаем поле ввода ( в этот раз уже после показа ошибки )

Python: Скопировать в буфер обмена
else:
- если нажата кнопка с другим текстом к примеру то строчка добавит ее в поле ввода

Python: Скопировать в буфер обмена
self.display.insert(tk.END, text)
- добавляем текст в поле ввода

Python: Скопировать в буфер обмена
if __name__ == "__main__":
- отвечает за проверку скрипта , выполняется ли он как основная программа

Python: Скопировать в буфер обмена
root = tk.Tk()
- Создаем главное окно Tkinter

Python: Скопировать в буфер обмена
calculator = Calculator(root)
- строчка создает копию можно сказать класса Calculator , передавая в него главное окно

Python: Скопировать в буфер обмена
root.mainloop()
- строчка запускает главный цикл Tkinter .

Вот что мы получим в конечном итоге
1722350904794.png




Поздравляю вы написали калькулятор с базовым дизайном и функционалом. В прошлой статье по питону я написал конвектор прокси (который работает через консоль ) .Давайте попробуем такой же скрипт написать только уже с форматом .pyw .Приступим , на конечном итоге мы получим такое
1722351637707.png



Python: Скопировать в буфер обмена
Код:
import tkinter as tk
from tkinter import filedialog, messagebox

class ProxyConverterApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Proxy Converter 2.0")

        self.create_widgets()

    def create_widgets(self):
        self.select_input_button = tk.Button(self.root, text="Выбрать файл ввода", command=self.load_input)
        self.select_input_button.pack(pady=10)
        self.select_output_button = tk.Button(self.root, text="Выбрать файл вывода", command=self.save_output)
        self.select_output_button.pack(pady=10)
        self.convert_button = tk.Button(self.root, text="Конвертировать", command=self.convert_proxies)
        self.convert_button.pack(pady=10)

    def load_input(self):
        self.input = filedialog.askopenfilename(filetypes=[("Text files", "*.txt")])
        if self.input:
            messagebox.showinfo("Информация", f"Выбран файл ввода: {self.input}")

    def save_output(self):
        self.output = filedialog.asksaveasfilename(filetypes=[("Text files", "*.txt")])
        if self.output:
            messagebox.showinfo("Информация", f"Выбран файл вывода: {self.output}")

    def convert_proxies(self):
        if not hasattr(self, 'input') or not hasattr(self, 'output'):
            messagebox.showwarning("Предупреждение", "Пожалуйста, выберите входной и выходной файлы.")
            return

        input_format = 'ip:port:user:pass'
        output_format = 'user:pass@ip:port'
      
        try:
            with open(self.input, 'r') as infile, open(self.output, 'w') as outfile:
                for line in infile:
                    line = line.strip()
                    converted_proxy = self.convert_proxy_format(line, input_format, output_format)
                    if converted_proxy:
                        outfile.write(converted_proxy + '\n')
            messagebox.showinfo("Информация", "Конвертация завершена успешно!")
        except Exception as e:
            messagebox.showerror("Ошибка", f"Произошла ошибка: {e}")

    def convert_proxy_format(self, proxy_str, input_format, output_format):
        try:
            components = proxy_str.split(':')
            if len(components) != len(input_format.split(':')):
                raise ValueError("Формат строки не соответствует ожидаемому")
            proxy_dict = {
                'ip': components[0],
                'port': components[1],
                'user': components[2],
                'pass': components[3]
            }
            output_str = output_format
            for key, value in proxy_dict.items():
                output_str = output_str.replace(key, value)
            return output_str
        except Exception as e:
            print(f"Ошибка: {e}")
            return None

if __name__ == "__main__":
    root = tk.Tk()
    app = ProxyConverterApp(root)
    root.mainloop()

Давайте разберем скрипт , надеюсь вы помните для чего он нужен (если кратко то он из этого ip:port:user:pass , делает это user:pass@ip:port, это все можно настроить под себя )

Python: Скопировать в буфер обмена
import tkinter as tk
- Библиотека создана для создания графического интерфейса

Python: Скопировать в буфер обмена
from tkinter import filedialog, messagebox
- filedialog - отвечает за открытия диалоговых окон можно сказать (для выбора файла ) - messagebox - отвечает за отображения сообщения пользователю (подробно почитайте выше )

Python: Скопировать в буфер обмена
class ProxyConverterApp:
- создаем класс ProxyConverterApp .В python классы используются для создания пользовательских объектов можно сказать (которые могут иметь методы и атрибуты )

Python: Скопировать в буфер обмена
def __init__(self, root):
- строчка определяет конструктор класса . Конструктор это можно сказать специальный метод , который автоматически вызывается при создании нового экземпляра (В нашем случаи этот конструктор принимает один аргумент и это root , который будет главным окном приложения

Python: Скопировать в буфер обмена
self.root = root
- присваиваем root

Python: Скопировать в буфер обмена
self.root.title("Proxy Converter 2.0")
- устанавливаем заголовок окна , через метод title мы изменяем текст можно сказать

Python: Скопировать в буфер обмена
self.create_widgets()
- Включаем в работу метод create_widgets для создания и размещения всех необходимых для нас виджетов на главном окне .Метод отвечает за создание кнопок

Python: Скопировать в буфер обмена
def create_widgets(self):
- определяем метод , который отвечает за создание элементов интерфейса

Python: Скопировать в буфер обмена
self.select_input_button = tk.Button(self.root, text="Выбрать файл ввода", command=self.load_input)
- создаем кнопку для выбора входного файла (туда будем загружать тхт файл откуда программа будет черпать данные для конвертации ) а так же строчка связывается с методом load_input

Python: Скопировать в буфер обмена
self.select_input_button.pack(pady=10)
- строчка размещает кнопку с отступом 10 пикселей по вертикали

Python: Скопировать в буфер обмена
self.select_output_button = tk.Button(self.root, text="Выбрать файл вывода", command=self.save_output)
- Строчка создает кнопку для выбора выходного файла ( туда будем загружать файл куда программа будет писать результат ) а так же связывает ее с методом save_output

Python: Скопировать в буфер обмена
self.select_output_button.pack(pady=10)
- строчка размещает кнопку с отступом 10 пикселей по вертикали

Python: Скопировать в буфер обмена
self.convert_button = tk.Button(self.root, text="Конвертировать", command=self.convert_proxies)
создает кнопку для собственно самой конвертации прокси и связывает ее с convert_proxies

Python: Скопировать в буфер обмена
self.convert_button.pack(pady=10)
- размещает кнопку с отступом 10 пикселей по вертикали

Python: Скопировать в буфер обмена
def load_input(self):
- определяет можно сказать метод , который выполняется при нажатии на кнопку "входного файла"

Python: Скопировать в буфер обмена
self.input = filedialog.askopenfilename(filetypes=[("Text files", "*.txt")])
- открывает окно для выбора файла ( с фильтром для тхт файлов )

Python: Скопировать в буфер обмена
if self.input:
- строчка проверяет был ли выбран файл

Python: Скопировать в буфер обмена
messagebox.showinfo("Информация", f"Выбран файл ввода: {self.input}")
- показывает сообщение о успешном выборе файла

Python: Скопировать в буфер обмена
def save_output(self):
- строчка определяет метод , который выполняется при нажатии на кнопку "выходного файла"

Python: Скопировать в буфер обмена
self.output = filedialog.asksaveasfilename(filetypes=[("Text files", "*.txt")])
- открывает окно для выбора файла куда будет записываться результат (так же стоит фильтр для тхт файлов)

Python: Скопировать в буфер обмена
if self.output:
- проверяет было ли выбрано все правильно

Python: Скопировать в буфер обмена
messagebox.showinfo("Информация", f"Выбран файл вывода: {self.output}")
- показывает о успешном выборе выходного файла

Python: Скопировать в буфер обмена
def convert_proxies(self):
- определяет опять же метод , который будет выполняться при конвертации прокси

Python: Скопировать в буфер обмена
if not hasattr(self, 'input') or not hasattr(self, 'output'):
- проверяет были ли выбраны входной и выходной файл

Python: Скопировать в буфер обмена
messagebox.showwarning("Предупреждение", "Пожалуйста, выберите входной и выходной файлы.")
- показывает юзеру сообщение если файл не был выбран

Python: Скопировать в буфер обмена
return
- останавливает метод если файл (загрузи или выгрузки )не был выбран

Python: Скопировать в буфер обмена
input_format = 'ip:port:user:pass'
- задаем формат выходных данных

Python: Скопировать в буфер обмена
output_format = 'user:pass@ip:port
- задаем выходной формат данных

Python: Скопировать в буфер обмена
try:
- начинает можно сказать основную часть кода , где будет выполняться основная логика а так же обработка исключений

Python: Скопировать в буфер обмена
with open(self.input, 'r') as infile, open(self.output, 'w') as outfile:
- открывает можно сказать входной файл для чтение а так же выходной файл для записи

Python: Скопировать в буфер обмена
for line in infile:
- цикл который будет отвечать за обработку каждой строки входного файла

Python: Скопировать в буфер обмена
line = line.strip()
- удаляет пробелы а так же и символы новой строки с обоих концов строки

Python: Скопировать в буфер обмена
converted_proxy = self.convert_proxy_format(line, input_format, output_format)
- конвертирует строчки в указанный выше формат

Python: Скопировать в буфер обмена
if converted_proxy:
- проверяет , была ли конвертация успешной

Python: Скопировать в буфер обмена
outfile.write(converted_proxy + '\n')
- строчка записывает конченый результат в выходной файл

Python: Скопировать в буфер обмена
messagebox.showinfo("Информация", "Конвертация завершена успешно!")
- Показывает сообщение юзеру о успешной конвертации прокси

Python: Скопировать в буфер обмена
except Exception as e:
- строчка отвечает за исключение , если они возникли

Python: Скопировать в буфер обмена
messagebox.showerror("Ошибка", f"Произошла ошибка: {e}")
- показывает юзеру ошибку если она есть

Python: Скопировать в буфер обмена
def convert_proxy_format(self, proxy_str, input_format, output_format):
- определяет метод который отвечает за конвертацию строки прокси из одного формата в нужный

Python: Скопировать в буфер обмена
Код:
try:
components = proxy_str.split(':')
- разбивает строку прокси на компоненты (ip pass port login как пример) используя двоеточие как разделитель компонентов

Python: Скопировать в буфер обмена
Код:
raise ValueError("Формат строки не соответствует ожидаемому") - если формат строки не соответствует то вызывает исключение

[CODE=python]proxy_dict = {'ip': components[0], 'port': components[1], 'user': components[2], 'pass': components[3]}
- создает можно сказать словарь связывая компоненты строки прокси с ключами 'ip', 'port', 'user' а так же 'pass'

Python: Скопировать в буфер обмена
output_str = output_format
- копирует если кратко итоговой результат в переменную output_str

Python: Скопировать в буфер обмена
for key, value in proxy_dict.items():
- строчка проходит по словарю proxy_dict

Python: Скопировать в буфер обмена
output_str = output_str.replace(key, value)
- заменяет ключи в строке output_str на соответствующие значения

Python: Скопировать в буфер обмена
return output_str
- возвращает можно сказать конвертированную строку прокси

Python: Скопировать в буфер обмена
except Exception as e:
- если возникли ошибки то обрабатывает их

Python: Скопировать в буфер обмена
print(f"Ошибка: {e}")
- сообщает юзеру о ошибке

Python: Скопировать в буфер обмена
return None
- возвращает none если возникла какая то ошибка

Python: Скопировать в буфер обмена
if __name__ == "__main__":
- проверка , запущен ли файл как основной можно сказать модуль
Python: Скопировать в буфер обмена
root = tk.Tk()
- создает собственно само окно
Python: Скопировать в буфер обмена
app = ProxyConverterApp(root)
- создает можно сказать экземпляр
Python: Скопировать в буфер обмена
root.mainloop()
- запускает собственно главный цикл

Вот и мы создали довольно простую программу но думаю полезную .В будущих статьях мы еще будем разбирать код и увеличивать функционал , подпишись чтобы не пропустить очередную статью =)

Давайте сейчас создадим простой генератор сид фразы , у которого будет 2 режима генерации . 1 - генерация 12 слов , 2 генерация 24 слов . А так добавим сохранение в буфер обмена и сохранение в файле . Не забывая про базовый дизайн , начнем

Вот что мы получим в конце
1722360601825.png



Python: Скопировать в буфер обмена
Код:
import tkinter as tk
from tkinter import filedialog, messagebox
from mnemonic import Mnemonic
import pyperclip

class SeedPhraseGeneratorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Генератор Сид Фразы")
        self.create_widgets()

    def create_widgets(self):
        self.length_label = tk.Label(self.root, text="Выберите длину сид фразы:", font=("Arial", 12))
        self.length_label.pack(pady=10)

        self.length_var = tk.StringVar(value='24')
        self.length_12 = tk.Radiobutton(self.root, text="12 слов", variable=self.length_var, value='12', font=("Arial", 12))
        self.length_12.pack(pady=5)
        self.length_24 = tk.Radiobutton(self.root, text="24 слова", variable=self.length_var, value='24', font=("Arial", 12))
        self.length_24.pack(pady=5)

        self.generate_button = tk.Button(self.root, text="Сгенерировать сид фразу", command=self.generate_seed_phrase, font=("Arial", 12))
        self.generate_button.pack(pady=20)

        self.copy_button = tk.Button(self.root, text="Скопировать в буфер обмена", command=self.copy_to_clipboard, font=("Arial", 12))
        self.copy_button.pack(pady=10)

        self.save_button = tk.Button(self.root, text="Сохранить в файл", command=self.save_to_file, font=("Arial", 12))
        self.save_button.pack(pady=10)

        self.seed_phrase_text = tk.Text(self.root, height=4, width=50, font=("Arial", 12), bd=2, relief=tk.SUNKEN)
        self.seed_phrase_text.pack(pady=10)

    def generate_seed_phrase(self):
        length = self.length_var.get()
        if length == '12':
            strength = 128
        elif length == '24':
            strength = 256
        else:
            messagebox.showwarning("Ошибка", "Выберите правильную длину сид фразы.")
            return
      
        mnemo = Mnemonic("english")
        seed_phrase = mnemo.generate(strength=strength)
        self.seed_phrase_text.delete(1.0, tk.END)
        self.seed_phrase_text.insert(tk.END, seed_phrase)
        messagebox.showinfo("Информация", "Сид фраза успешно сгенерирована!")

    def copy_to_clipboard(self):
        seed_phrase = self.seed_phrase_text.get(1.0, tk.END).strip()
        if seed_phrase:
            pyperclip.copy(seed_phrase)
            messagebox.showinfo("Информация", "Сид фраза скопирована в буфер обмена!")
        else:
            messagebox.showwarning("Предупреждение", "Сначала сгенерируйте сид фразу.")

    def save_to_file(self):
        file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files", "*.txt")])
        if file_path:
            seed_phrase = self.seed_phrase_text.get(1.0, tk.END).strip()
            if seed_phrase:
                with open(file_path, 'w') as file:
                    file.write(seed_phrase)
                messagebox.showinfo("Информация", "Сид фраза успешно сохранена в файл!")
            else:
                messagebox.showwarning("Предупреждение", "Сначала сгенерируйте сид фразу.")

if __name__ == "__main__":
    root = tk.Tk()
    app = SeedPhraseGeneratorApp(root)
    root.mainloop()

Python: Скопировать в буфер обмена
import tkinter as tk
- импортируем библиотеку Tkinter ( упростим его и будем называть tk) , зачем нужна это библиотека можете почитать выше

Python: Скопировать в буфер обмена
from tkinter import filedialog, messagebox
- импортируем модули из tk .

Python: Скопировать в буфер обмена
Код:
from mnemonic import Mnemonic - импортируем класс Mnemonic из библиотеки mnemonic , который в нашем случаи будет использоваться для генерации и работы с сид-фразами

[CODE=python]import pyperclip
- Импортируем библиотеку pyperclip для работы с копированием текста

Python: Скопировать в буфер обмена
class SeedPhraseGeneratorApp:
- определяем новый класс SeedPhraseGeneratorApp который будет отвечать за графическое приложение

Python: Скопировать в буфер обмена
def __init__(self, root):
- метод конструктор класса , которой отвечает за можно сказать создание нового обьекта SeedPhraseGeneratorApp

Python: Скопировать в буфер обмена
self.root = root
- Сохраняет ссылку на главное окно Tkinter

Python: Скопировать в буфер обмена
self.root.title("Генератор Сид Фразы")
- устанавливает заголовка окна tkinter самого приложения
Python: Скопировать в буфер обмена
self.create_widgets()
- отвечает за вызывание метода create_widgets который может по названию поняли создает и размещает все виджеты в окне

Python: Скопировать в буфер обмена
self.length_label = tk.Label(self.root, text="Выберите длину сид фразы:", font=("Arial", 12))
- строчка создает метку "Label" для выбора длины сид фразы с указанным нам текстом а так же устанавливает шрифт

Python: Скопировать в буфер обмена
self.length_label.pack(pady=10)
- размещает метку в окне добавляя вертикальные отступы

Python: Скопировать в буфер обмена
self.length_var = tk.StringVar(value='24')
- отвечает за создания переменной StringVar которая в свою очередь отвечает за хранение режима (12 или 24 слова)

Python: Скопировать в буфер обмена
self.length_12 = tk.Radiobutton(self.root, text="12 слов", variable=self.length_var, value='12', font=("Arial", 12))
- строчка отвечает за создание кнопки для выбора длины сид фразы в данном случаи 12 слов

Python: Скопировать в буфер обмена
self.length_12.pack(pady=5)
- размещает кнопку в окне с вертикальными отступами ( по 5 пикселей )

Python: Скопировать в буфер обмена
self.length_24 = tk.Radiobutton(self.root, text="24 слова", variable=self.length_var, value='24', font=("Arial", 12))
- строчка создает кнопку для выбора сид фразы ( в данном случаи 24 слова )

Python: Скопировать в буфер обмена
self.length_24.pack(pady=5)
- размещает кнопку в окне с отступами по 5 пикселей

Python: Скопировать в буфер обмена
self.generate_button = tk.Button(self.root, text="Сгенерировать сид фразу", command=self.generate_seed_phrase, font=("Arial", 12))
- создание кнопки которая отвечает за генерацию сид фразы с нашим указанным текстом .А так же привязывает ее к generate_seed_phrase

Python: Скопировать в буфер обмена
self.generate_button.pack(pady=20)
- размещает кнопку в окне с отступами по 20 пикселей

Python: Скопировать в буфер обмена
self.copy_button = tk.Button(self.root, text="Скопировать в буфер обмена", command=self.copy_to_clipboard, font=("Arial", 12))
- строчка создает объект button и размещает его в основном окне self.root, text="Скопировать в буфер обмена" - текст который будет отображаться на кнопке , command=self.copy_to_clipboard - это команда будет вызвана только при нажатии на кнопку .font=("Arial", 12) - устанавливаем подходящий шрифт

Python: Скопировать в буфер обмена
self.copy_button.pack(pady=10)
- размещаем кнопку в окне с отступами , чтобы создать приятный дизайн

Python: Скопировать в буфер обмена
self.save_button = tk.Button(self.root, text="Сохранить в файл"
- создаем обьект button (кнопка) для сохранение сид фразы в файл

Python: Скопировать в буфер обмена
command=self.save_to_file, font=("Arial", 12))
- данная строчка будет вызвана опять же при нажатии , font=("Arial", 12)) - установка подходящего шрифта и размета текста

Python: Скопировать в буфер обмена
self.save_button.pack(pady=10)
- строчка размещает кнопку в отступами по вертикали

Python: Скопировать в буфер обмена
self.seed_phrase_text = tk.Text(self.root, height=4, width=50, font=("Arial", 12), bd=2, relief=tk.SUNKEN)
- создание текстового поля где будет отображаться наша сгенерированная сид фраза ,height=4 - высота данного поля ,width=50 - ширина данного поля ,font=("Arial", 12) - установка шрифта и размера текста опять же в данном поле ,bd=2 - устанавливаем толщину границы текстового поля ,relief=tk.SUNKEN - устанавливает стиль границы , окно будет выглядеть как будто вдавленное в окно

Python: Скопировать в буфер обмена
self.seed_phrase_text.pack(pady=10)
- строчка предназначена для размещение текстового поля в окне с отступами

Python: Скопировать в буфер обмена
length = self.length_var.get()
- получаем выбранное юзером значение длины сид фразы (12 или 24) из переменной self.length_var

Python: Скопировать в буфер обмена
if length == '12':
- проверяет на наличии выбора 12 ти слов

Python: Скопировать в буфер обмена
strength = 128
- Устанавливает значение strength в 128 бит для генерации 12 слов.

Python: Скопировать в буфер обмена
elif length == '24':
- проверяет на выбор юзера ( в данном случаи 24 слов ), если юзер выбрал 24 то строчка устанавливает strength в 256 бит

Python: Скопировать в буфер обмена
else:
- выполняется если length не равно 12 или 24

Python: Скопировать в буфер обмена
messagebox.showwarning("Ошибка", "Выберите правильную длину сид фразы.")
- предупреждает юзера о ошибке , если пользователь выбрал не верную длину сид фразы

Python: Скопировать в буфер обмена
return
- можно сказать строчка прерывает выполнение метода , если сид фраза указана неверно ( ничего не происходит дальше )

Python: Скопировать в буфер обмена
mnemo = Mnemonic("english")
- строчка создает обьект Mnemonic для работы со сид фразами на английском языке

Python: Скопировать в буфер обмена
seed_phrase = mnemo.generate(strength=strength)
- генерирует сид фразу с заданной силой , используя объект mnemonic . Сид фраза создаётся на основе выбор юзера

Python: Скопировать в буфер обмена
self.seed_phrase_text.delete(1.0, tk.END)
- очищает текстовое поле

Python: Скопировать в буфер обмена
self.seed_phrase_text.insert(tk.END, seed_phrase)
- показывает сгненерированную сид фразу

Python: Скопировать в буфер обмена
messagebox.showinfo("Информация", "Сид фраза успешно сгенерирована!")
- отображает инфо сообщение о успешной генерации

Python: Скопировать в буфер обмена
seed_phrase = self.seed_phrase_text.get(1.0, tk.END).strip() - self.seed_phrase_text.get(1.0, tk.END)
- получает текст из текстового поля self.seed_phrase_text означает начало текста а tk.END указывает на конец текста

Python: Скопировать в буфер обмена
if seed_phrase:
- строчка проверяет не является ли seed_phrase пустой строкой .Если строчка к примеру не пустая то выполняется другая часть кода

Python: Скопировать в буфер обмена
pyperclip.copy(seed_phrase)
- используем библиотеку pyperclip для копирования сид фразы в буфер обмена .

Python: Скопировать в буфер обмена
messagebox.showinfo("Информация", "Сид фраза скопирована в буфер обмена!")
- показывает сообщение пользователю и говорит о успешном копировании

Python: Скопировать в буфер обмена
else:
- строчка активна если seed_phrase пустая

Python: Скопировать в буфер обмена
messagebox.showwarning("Предупреждение", "Сначала сгенерируйте сид фразу.")
- строчка дает знать пользователю что нельзя скопировать что либо с буфера обмена если юзер еще не сгенерировал сид фразу

Python: Скопировать в буфер обмена
file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files", "*.txt")])
- открывает выбор файлов для сохранение файлов , а так же дает возможность выбрать место и имя файла для сохранение

Python: Скопировать в буфер обмена
defaultextension=".txt"
- Устанавливаем расширение по умолчанию для сохраняемого файла как .txt

Python: Скопировать в буфер обмена
filetypes=[("Text files", "*.txt")]
- ограничиваем выбор файлов только текстовыми файлами с расширением .txt

Python: Скопировать в буфер обмена
if file_path:
- строчка проверяет был ли выбран путь для сохранение. Если путь не пустой то выполняется другая часть кода

Python: Скопировать в буфер обмена
seed_phrase = self.seed_phrase_text.get(1.0, tk.END).strip()
- получает текст из тхт файла self.seed_phrase_text и удаляет начальные и конечные пробелы

Python: Скопировать в буфер обмена
if seed_phrase:
- строчка проверяет не является ли текс пустым .Если текст есть то программа выполняет другую часть кода

Python: Скопировать в буфер обмена
with open(file_path, 'w') as file:
- открывает файл по указанному пути .Если файл не существует то программа ее создаст а with автоматически закроет файл после завершения работы с ним

Python: Скопировать в буфер обмена
file.write(seed_phrase)
- записывает саму сид фразу

Python: Скопировать в буфер обмена
messagebox.showinfo("Информация", "Сид фраза успешно сохранена в файл!")
- показывает сообщение пользователю если сохранение сих фразы прошла успешна

Python: Скопировать в буфер обмена
else:
- строчка отвечает за выполнение кода если текстовое поле пустое

Python: Скопировать в буфер обмена
messagebox.showwarning("Предупреждение", "Сначала сгенерируйте сид фразу.")
- если пользователь пытается сохранить поле то программа выдаст такое сообщение

Python: Скопировать в буфер обмена
if __name__ == "__main__":
- проверяет , что скрипт выполняется как основная программа

Python: Скопировать в буфер обмена
root = tk.Tk()
- создает окно tk ( это окно будет содержать в себе все виджеты и элементы интерфейса )

Python: Скопировать в буфер обмена
app = SeedPhraseGeneratorApp(root)
- создает копию SeedPhraseGeneratorApp передавая ему основное окно tk ( он управляет интерфейсом и функциональностью )

Python: Скопировать в буфер обмена
root.mainloop()
- запускает основной цикл обработки tk .Цикл продолжает выполняться пока окно открыто и завершается когда окно закроется

так же я подготовил для вас бонусный скрипт , давайте под конец разберем простую программу которую буде показывать время
В конце получим такой результат
1722367508181.png



Python: Скопировать в буфер обмена
Код:
import tkinter as tk
import time

class SimpleClockApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Часы")
        self.time_label = tk.Label(self.root, font=("Arial", 48), bg="white", fg="black")
        self.time_label.pack(padx=20, pady=20)

        self.update_time()

    def update_time(self):
        current_time = time.strftime("%H:%M:%S")

        self.time_label.config(text=current_time)

        self.root.after(1000, self.update_time)

if __name__ == "__main__":
    root = tk.Tk()
    app = SimpleClockApp(root)
    root.mainloop()


Python: Скопировать в буфер обмена
import tkinter as tk
- импортируем библиотеку tkinter и называем ее tk , подробнее можно почитать выше

Python: Скопировать в буфер обмена
import time
- импортируем библиотеку time , которая предназначена для работы с функциями .В нашей программе она нужна будет для получение реального времени

Python: Скопировать в буфер обмена
class SimpleClockApp:
- создает класс SimpleClockApp которая будет управлять нагим графическим приложением

Python: Скопировать в буфер обмена
def __init__(self, root):
- конструктор класса который инициализирует root

Python: Скопировать в буфер обмена
self.root = root
- строчка сохраняет ссылку на главное окно self.root

Python: Скопировать в буфер обмена
self.root.title("Часы")
- строчка создает заголовок окна

Python: Скопировать в буфер обмена
self.time_label = tk.Label(self.root, font=("Arial", 48), bg="white", fg="black")
- создает метку Label для отображении времени , font=("Arial", 48) задаем шрифт с размером 48 , bg="white" - устанавливаем белый фон для метки ,fg="black" - устанавливаем черный текст для текста

Python: Скопировать в буфер обмена
self.time_label.pack(padx=20, pady=20)
- располагаем метку в окне с отступами

Python: Скопировать в буфер обмена
self.update_time()
- отвечает за обновление времени сразу после инициализации

Python: Скопировать в буфер обмена
def update_time(self):
- строчка определяет метод update_time которая будет отвечать за обновление времени на экране

Python: Скопировать в буфер обмена
current_time = time.strftime("%H:%M:%S")
- строчка получает текущее время в формате часы-минуту-секунды , time.strftime - форматирует текущее время в строчку

Python: Скопировать в буфер обмена
self.time_label.config(text=current_time)
- обновляем текст self.time_label чтобы отображать текущее время

Python: Скопировать в буфер обмена
self.root.after(1000, self.update_time)
- строчка отвечает за вызов можно сказать времени через 1 секунду

Python: Скопировать в буфер обмена
if __name__ == "__main__":
- строчка убеждается что код ниже выполняется только при запуске скрипта на прямую
Python: Скопировать в буфер обмена
root = tk.Tk()
- создаем основное окно приложения
Python: Скопировать в буфер обмена
app = SimpleClockApp(root)
- создаем копию класса SimpleClockApp передавая основное окно rooy

Python: Скопировать в буфер обмена
root.mainloop()
- строчка запускает главный цикл обработки

На этой ноте статья подошла к концу , я надеюсь я помог вам в изучении формата .pyw . В этой статье мы разобрали 4 просыте проги , спасибо за внимание .Был бы рад если вы подсказали на какую тему в дальнейшем писать статьи . успехов всем , подержите меня лайком ( ну пожалуйста ) =)
 
Сверху Снизу