Как изящно выйти из приложения, запущенного с twistd? - PullRequest
12 голосов
/ 17 марта 2011

У меня есть клиент jabber, который читает со своего стандартного устройства и публикует сообщения PubSub.Если я получаю EOF на stdin, я хочу завершить работу клиента.

Сначала я попытался sys.exit(), но это вызывает исключение, и клиент не выходит.Затем я провел поиск и обнаружил, что мне следует позвонить reactor.stop(), но я не могу сделать эту работу.Следующий код в моем клиенте:

from twisted.internet import reactor
reactor.stop()

В результате exceptions.AttributeError: 'module' object has no attribute 'stop'

Что мне нужно сделать, чтобы twistd закрыл мое приложение и завершил работу?

РЕДАКТИРОВАНИЕ 2

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

twisted.internet.error.ReactorNotRunning: Can't stop reactor that isn't running.

После исключения twistd выключается.Я думаю, что это может быть вызвано вызовом MyClient.loop в MyClient.connectionInitialized.Возможно, мне нужно отложить вызов на потом?

РЕДАКТИРОВАТЬ

Вот файл .tac для моего клиента

import sys

from twisted.application import service
from twisted.words.protocols.jabber.jid import JID

from myApp.clients import MyClient

clientJID = JID('client@example.com')
serverJID = JID('pubsub.example.com')
password = 'secret'

application = service.Application('XMPP client')
xmppClient = client.XMPPClient(clientJID, password)
xmppClient.logTraffic = True
xmppClient.setServiceParent(application)

handler = MyClient(clientJID, serverJID, sys.stdin)
handler.setHandlerParent(xmppClient)

Какой яm вызывает с помощью

twistd -noy sentry/myclient.tac < input.txt

Вот код для MyClient:

import os
import sys
import time
from datetime import datetime

from wokkel.pubsub import PubSubClient

class MyClient(PubSubClient):
    def __init__(self, entity, server, file, sender=None):
        self.entity = entity
        self.server = server
        self.sender = sender
        self.file = file

    def loop(self):
        while True:
            line = self.file.readline()
            if line:
                print line
            else:
                from twisted.internet import reactor
                reactor.stop()

    def connectionInitialized(self):
        self.loop()

Ответы [ 3 ]

7 голосов
/ 17 марта 2011
from twisted.internet import reactor
reactor.stop()

, что должно работать.Тот факт, что это не означает, что-то еще не так в вашем приложении.Я не могу понять, что не так из предоставленной вами информации.

Можете ли вы предоставить больше (всего) кода?


РЕДАКТИРОВАТЬ:

Хорошо,теперь проблема в том, что вы не останавливаете свой собственный цикл while True, поэтому он будет продолжать цикл и в конечном итоге снова остановит реактор.

Попробуйте это:

from twisted.internet import reactor
reactor.stop()
return

Теперь яподозреваю, что ваш цикл не очень хорошая вещь для управляемой событиями среды.Хотя вы просто печатаете строки, это нормально, но в зависимости от того, что вы действительно хотите сделать (я подозреваю, вы будете делать больше, чем просто печатать строки), вам придется реорганизовать этот цикл для работы с событиями.

5 голосов
/ 20 апреля 2016

Используйте reactor.callFromThread(reactor.stop) вместо reactor.stop.Это должно решить проблему.

1 голос
/ 24 ноября 2012

Раньше я делал это так (в обработчике sigint приложения, которое не называется твист):

reactor.removeAll()
reactor.iterate()
reactor.stop()

Я не уверен на 100%, что это правильный путь, но витая рада

то же самое приложение, запущенное в TAC, обрабатывается напрямую обработчиком сигналов twistd, я нашел этот вопрос, потому что у меня есть некоторые запросы клиента rpc, которые я бы ожидал и обработал результат перед выходом, и похоже, что twistd просто убиваетреактор, не позволяя завершить вызов

...