• XSS.stack #1 – первый литературный журнал от юзеров форума

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

network work

HDD-drive
Пользователь
Регистрация
11.07.2024
Сообщения
47
Реакции
5
Гарант сделки
3
Автор network work
Источник https://xss.pro



Всем здравствуйте я решил создать статью где подробно опишу что такое формат .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 просыте проги , спасибо за внимание .Был бы рад если вы подсказали на какую тему в дальнейшем писать статьи . успехов всем , подержите меня лайком ( ну пожалуйста ) =)
 
Последнее редактирование:
Блин, не обижайся конечно, я начал читать статью и после того как ты объяснил что за формат .pyw ( после вступления ) тебя понесло куда то в калькуляторы, конверторы итд итп, я даже читать не стал, так как по большей части ты начал объяснять про программы, основу ( что такое pyw и зачем нужен ) ты объяснил буквально за 10-15 строк ( ну это и правильно, тут нечего рассказывать да и он бесполезный формат как и pyc ), я дцмаю для решиния убрать окно можно оьратиться к компилятору и поставить нужный флаг при компиляции ( зависит от компилятора ). Это куда лучше чем мастерить что то с форматами, тем более если ты работаешь на пользователей то будь готов что у них не будет установлен Python на ПК. Просто это так же безсмысленно как использовать в Си WinMain вместо main как точку входа, когда это просто решается компилятором и флагом.

Если ты пишешь подобные статьи и мало материала, то лучше бы ты объединил форматы что бы рассказать сразу про все (.py, .pyw, .pyc, .pyd). Например .pyc работает быстрее чем .py обычный скрипт, потому что он как бы уже скомпилирован для интерпритатора и "c" на конце на сколько помню присобачили так как код компилится ( как и nuitka ) через Си инструкции или либы, я в это не вдавался особо. Вообщем я надеюсь ты понял суть претензии и совета.
 
Расширение файла это не формат файла. И вообще нахрена это здесь. В инете куча ресусров по питону для совсем новичков.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх