Как прерывать потоки в Twisted?

У меня проблема со следующим кодом. В моей реальной ситуации логика, инкапсулированная SomeClass, имеет блокирующую логику, поэтому мне нужно, чтобы она вызывалась с помощью reactor.callFromThread(). Я хочу, чтобы цикл в SomeClass.run() останавливался, когда я выдаю сигнал sigint, и я понимаю, что добавление некоторого кода для этого в хук addSystemEvent должно справиться с этим. Я думаю, что это может быть больше проблемой с моим пониманием Python и потоковой передачи, чем с самим Twisted.

from twisted.internet import reactor
import time

class SomeClass():
    def __init__(self):
        self.running = False

    def run(self):
        self.running = True
        while(self.running):
            print('foo')
            time.sleep(5)

    def stop(self):
        print('stopping')
        self.running = False

someClassInstance = SomeClass()

def cleanup():
    someClassInstance.stop()

reactor.addSystemEventTrigger('before', 'shutdown', cleanup)
reactor.callFromThread(someClassInstance.run)
reactor.run()

person Cera    schedule 07.03.2012    source источник


Ответы (1)


Невозможно безопасно и универсально прервать поток в таком языке программирования, как Python. Раньше эта функция была в Java, но ее удалили потому что это по своей сути небезопасно. (В Java есть новая функция Thread.interrupt, которая представляет собой ограниченную версию с меньшим количеством проблем, но все же усложняет задачу написания многопоточного кода).

Вот почему Twisted предоставляет множество способов избежать потоков. Если они вам не нужны, не используйте их. Например, вместо вызова time.sleep(n); foo() просто выполните reactor.callLater(n, foo), и вы получите тот же эффект, за исключением того, что callLater возвращает объект, который вы можете использовать, чтобы легко отменить или отложить выполнение foo, если это еще не произошло.

Если у вас есть пример того, что вы на самом деле пытаетесь сделать, а не заменяете "time.sleep" на "и затем что-то происходит", пожалуйста, откройте другой вопрос, поясняющий это. Ответ на самом деле зависит от того, что вы делаете — действительно ли вы ждете вовремя? Блокировка ввода-вывода для другого процесса? Другая машина? У Twisted есть соответствующие возможности для всего этого.

person Glyph    schedule 07.03.2012
comment
По сути, я блокирую сетевые вызовы: вызываю некоторые устаревшие библиотеки, которые выполняют синхронную работу клиента IMAP. На данный момент у меня это, по крайней мере, работает, используя callInThread() вместо callFromThread(), но я хотел бы знать, как я могу использовать песочницу для моего блокирующего кода более правильным способом Twisted. Изменить: я только что понял, что могу сделать это с помощью deferToThread(), что кажется лучше, но я все еще использую потоки! - person Cera; 07.03.2012