Python GTK / Threading / Сокеты Ошибка - PullRequest
0 голосов
/ 12 сентября 2010

Я пытаюсь создать приложение Python, используя pyGTK, шаги и сокеты.У меня странная ошибка, но, учитывая все задействованные модули, я не совсем уверен, где ошибка.Я выполнил небольшую отладку с некоторыми операторами печати, чтобы немного сузить ситуацию, и я думаю, что ошибка находится где-то в этом фрагменте кода:

    self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    self.sock.connect(("localhost", 5005))
    self.collectingThread = threading.Thread(target=self.callCollect)
    self.collectingThread.daemon = True
    self.collectingThread.start()

def callCollect(self):
    gobject.timeout_add(500, self.collectData)

def collectData(self):
    print "hello"
    try:
        print self.sock.recv(1024)
    except:
        print "except"
    print "return"
    return True

Итак, в основном я пытаюсь установить сокетподключитесь к «серверному» сценарию (который на самом деле является просто еще одним сценарием Python, работающим локально) и создайте отдельный поток для сбора всех входящих данных из серверного сценария.Этот поток настроен на запуск метода collectData каждые 500 миллисекунд.

После вставки операторов печати в метод collectData я замечаю следующее при запуске программы:

- изначально графический интерфейс полностьюфункциональный

- после этого в терминале печатается следующее:

hello
**all data received from server script and printed here**
return
hello

- после того, как текст напечатан в терминале, графический интерфейс пользователя становится полностью неработоспособным (кнопки нельзя нажимать и т. д.)и мне нужно принудительно завершить работу, чтобы закрыть приложение

Кажется, что происходит то, что поток выводит «привет», печатает данные с сервера и печатает «возврат».Через 500 миллисекунд он снова запускает метод collectData, печатает «привет», а затем пытается распечатать данные с сервера.Однако из-за того, что не осталось данных, возникает исключение, но по неизвестной причине он не выполняет код в блоке исключений, и все просто зависает оттуда.

Есть идеи о том, что идет не так?

Ответы [ 2 ]

1 голос
/ 12 сентября 2010

timeout_add планирует действие, которое должно произойти в главном потоке - поэтому recv просто блокирует основной поток (когда он просто ожидает данные) и, следовательно, графический интерфейс, поэтому нет исключение, если вы не установили таймаут или не установили сокет как неблокирующий.

Вам нужно делегировать получение потоку от запланированного действия , а не наоборот, чтобы получить желаемый эффект: например, создайте поток. ожидание объекта события, и запланированное действие сигнализирует об этом событии каждые 500 миллисекунд.

0 голосов
/ 12 сентября 2010

Нет, очевидно, что вызовы sock.recv блокируются, потому что сокет еще не был закрыт, а получение сокета блокируется по умолчанию.Убедитесь, что вы закрыли соединение в какой-то момент.

Было бы более разумно выполнить вызов приема в новом потоке, иначе это может заблокировать графический интерфейс, поскольку ваша текущая реализация выполняет вызов recv вПоток GUI (используя timeout_add).То, как вы в настоящее время делаете это, имеет смысл, только если ответ получен очень быстро и / или вам нужен доступ к виджетам.

Кстати, создание нового потока для вызова gobject.timeout_add совершенно не нужно.timeout_add() и idle_add() регистрируют указанную функцию обратного вызова и немедленно возвращаются.Затем цикл событий GTK автоматически выполняет обратный вызов по истечении времени ожидания (или в состоянии ожидания для idle_add).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...