Я пытаюсь создать пакет python для вызова неблокирующих команд. Я придумал простой класс «Исполнитель», который будет иметь поток и очередь с командами для выполнения одной за другой. Хотя кажется, что исключение команд работает, программа никогда не завершает свою работу, поскольку класс-исполнитель никогда не удаляется сборщиком мусора после того, как объект выходит из области видимости.
import threading
import queue
import time
import weakref
class Commands:
"""Class for all Commands"""
Command: str = ""
IsDone: bool = False
WasSuccessfull: bool = False
Value: object = None
def __init__(self, InputCommand):
self.Command = InputCommand
def GetValue(self) -> object:
while not self.IsDone:
time.sleep(0.01)
return self.Value
def WaitForFinished(self):
while not self.IsDone:
time.sleep(0.01)
class Executer:
CommandQueue: queue.Queue = queue.Queue()
Worker: threading.Thread = None
def __init__(self):
self.Worker = threading.Thread(target=weakref.proxy(Executer.__WorkerThread__), args=(weakref.proxy(self) ,))
self.Worker.start()
def __del__(self):
print("Exiting")
self.AddCommand("__STOP__")
self.Worker.join()
def AddCommand(self, CommandText) -> Commands:
Command = Commands(CommandText)
self.CommandQueue.put(Command)
return Command
def __WorkerThread__ (self):
while True:
if self.CommandQueue.empty():
time.sleep(0.01)
else:
Command = self.CommandQueue.get()
print(Command.Command)
# Emulate some work
time.sleep(0.5)
Command.IsDone = True
Command.WasSuccessfull = True
if(Command.Command == "__STOP__"):
break
if __name__ == "__main__":
exe = Executer()
Command = exe.AddCommand("Yeah 0")
exe.AddCommand("Yeah 1")
exe.AddCommand("Yeah 2")
exe.AddCommand("Yeah 3")
exe.AddCommand("Yeah 4")
x = Command.GetValue()
print(x)
print("Done")
Похоже, та же проблема, что и здесь: Поток Python. Поток, области и сборка мусора
Хотя решение (в его комментариях) кажетсяработать на автора, это не работает для меня после его интеграции. Основной поток будет выполняться через все мои команды, но подзаголовок не умрет, так как класс "executeer" не будет удален.
Класс будет удален, если пользователь специально вызвалdel exe
, но это не очень хороший подход к Python, так как пользователю моего пакета всегда нужно будет самостоятельно очищать класс.