@re3r0

Как решить проблему с видимостью переменной root?

Суть скрипта просто спамить новыми окнами с изображением
from random import randint
import tkinter as tk
from PIL import ImageTk, Image
import telebot;
from time import sleep

bot = telebot.TeleBot('token');

def createNewWindow(root, img):
  for i in range(100):
    newWindow = tk.Toplevel(root)
    labelExample = tk.Label(newWindow, image = img)
    w =  randint(0, newWindow.winfo_screenwidth())
    h =  randint(0, newWindow.winfo_screenheight())
    newWindow.geometry('+{}+{}'.format(w, h))
    labelExample.pack()

@bot.message_handler(content_types=['text'])
def get_command(message):
    if message.text == "Start":
      root = tk.Tk()
      img = ImageTk.PhotoImage(Image.open('lol.png'))
      createNewWindow(root, img)
      root.mainloop()
    elif message.text == "Stop":
      root.destroy()
bot.polling(none_stop=True, interval=0)

после команды Stop в Телеграмм боте выходит ошибка

File "main.py", line 26, in get_command
root.destroy()
UnboundLocalError: local variable 'root' referenced before assignment

Забавно что скприпт после ошибки, все окна закрывает как и надо, но после архиваций в SFX архив окна закрыватся сами по себе не хотят :/

И если не сложно можете подсказать как зациклить скрипт ? что бы после комманды Stop окна закрывались но патом можно было опять начять спам ?
  • Вопрос задан
  • 59 просмотров
Пригласить эксперта
Ответы на вопрос 1
Vindicar
@Vindicar
RTFM!
@bot.message_handler(content_types=['text'])
def get_command(message):
    if message.text == "Start":
      root = tk.Tk()
      img = ImageTk.PhotoImage(Image.open('lol.png'))
      createNewWindow(root, img)
      root.mainloop()
    elif message.text == "Stop":
      root.destroy()

Ух как всё запущено.
Во-первых, если ты ввёл Start, то get_command() создаёт локальную root, настраивает её, и уходит в бесконечный цикл внутри root.mainloop(). Я не знаю как pytelegrambotapi разруливает это, но бот после такого должен просто встать колом, пока все окна не будут закрыты. Подозреваю что обработчик вызывается в отдельном потоке, но фз. В любом случае, не надо так делать. Лучше иметь один root, который крутится внутри mainloop() в отдельном потоке всё время работы скрипта, а окна создавать и удалять по мере надобности, не создавая и не убивая root.
Вообще подружить бота с оконным интерфейсом - задача нетривиальная.
Во-вторых, переменная root - локальная. Она существует только внутри того экземпляра get_command(), который был вызван с командой старт. Если ты вызываешь его с командой Stop, у тебя запускается отдельный экземпляр, где выполняется только ветка Stop - а в этой ветке root объявлен не был, он был объявлен только в ветке Start, в другом экземпляре.
В-третьих, окна будут спамиться только на той машине где запущен бот. Это так, на всякий случай.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы