Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 25, 2008 15:30:46

van-gog
От:
Зарегистрирован: 2008-04-19
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

[q] Twisted

Доброго времени суток!

У меня возникла проблема с Twisted.internet.threads
есть код:
…..
def getData(url):
res = getPage(url)
return

def resCallBack(data):
print data
reactor.stop()

d = threads.deferToThread(getData, ‘some site’)
d.addCallback(resCallBack)
reactor.run()
После работы этого скрипта мне выдает следующее:

<Deferred at 0xfd1878>
Но по идее должно выдать код страницы…
В чем проблема ?
ЗЫ: в гугле смотрел…



Отредактировано (Май 7, 2008 17:27:37)

Офлайн

#2 Апрель 25, 2008 16:51:03

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

[q] Twisted

Все правильно.
twisted.web.getPage возвращает именно deferred, который ты и видишь - это раз.
getPage не может быть вызвана из потока - только из реактора (есть хитрые возможности, но они сейчас не интересны). deferToThread делали не для твоего случая. Это два.



Офлайн

#3 Апрель 25, 2008 17:02:00

van-gog
От:
Зарегистрирован: 2008-04-19
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

[q] Twisted

Андрей Светлов
Все правильно.
twisted.web.getPage возвращает именно deferred, который ты и видишь - это раз.
getPage не может быть вызвана из потока - только из реактора (есть хитрые возможности, но они сейчас не интересны). deferToThread делали не для твоего случая. Это два.
А для каких целей делали deferToThread?
И каким образом это можно обойти, если не секрет?



Отредактировано (Апрель 25, 2008 17:04:19)

Офлайн

#4 Апрель 25, 2008 18:14:26

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

[q] Twisted

deferToThread нужен для выполнения долгих операций, не знающих о реакторе, в пуле потоков (в отдельном потоке, для простоты понимания). Примеры таких операций - “длинные” обращения к базе данных, выполнение долгих вычислений.

У тебя другой случай. Нужно делать

def onPage(page):
print page

def stopReactor(arg):
reactor.stop()

d = getPage('some site')
d.addCallback(onPage).addCallback(stopReactor)
reactor.run()

Остановка реактора после получения странички - только для теста, конечно же. Реактор должен работять всю жизнь приложения.



Офлайн

#5 Апрель 25, 2008 18:49:32

van-gog
От:
Зарегистрирован: 2008-04-19
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

[q] Twisted

Мне как раз нужно чтобы страничка скачивалась в потоке, и из потока вызывался колбек.
В моем случае сраничка содержит ооочень много записей, и таких страничек за определенный промежуток времени нужно обработать несколько.
На скачку одной страницы уходит приблизительно 6-10 секунд.



Отредактировано (Апрель 25, 2008 18:52:17)

Офлайн

#6 Апрель 25, 2008 19:25:05

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

[q] Twisted

Вариант 2

.....
def getData(url):
page = urllib2.urlopen(url)
body = page.read()
# process page
ret = process(body)
return [url, res]

def resCallBack(data):
print data[1]
reactor.stop()

d = threads.deferToThread(getData, 'some site')
d.addCallback(resCallBack)
reactor.run()
Третий вариант - переписать twisted.web.client.HTTPClientFactory, чтобы вытягивала и обрабатывала страничку по частям. Это - сложнее.



Офлайн

#7 Май 7, 2008 16:49:09

van-gog
От:
Зарегистрирован: 2008-04-19
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

[q] Twisted

Спасибо за ответ :)

Теперь возник другой вопрос:
как запустить одновременно 10 потоков, каждый из которых после выполнения добавляет в список задач новую задачу, и она уже, если количество потоков < 10, тоже запускается в отдельном потоке.

Я сделал так:

def run():
if len(threads) < 10:
if len(tasks) == 0:
reactor.stop()
pass
else:
if len(tasks) > 0:
function, params, callback = tasks.pop(0)
threads.deferToThread(function, params).addCallback(callback)
reactor.run()
threads.append(params)
sleep(.1) #чтоб не слишком загружать процессор

Но этот кусок кода работает не совсем правильно :(
Первое задание выполняется, а остальные - нет :(
Помогите пожалуйста.
ЗЫ: гугл ответа не дал :(



Отредактировано (Май 7, 2008 17:27:06)

Офлайн

#8 Май 7, 2008 18:14:42

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

[q] Twisted

:)
Ты должен просто ничего не делать.
реактор уже содержит пул потоков. С максимальным размером именно в 10 штук.
Поэтому просто бомби threads.deferToThread сколько хочешь раз. Больше десяти одновременно выполняться не будет.
sleep - тоже не нужен. У тебя реактор должен все время крутиться.

Код инициализации пула в twisted.internet.base:_initThreadPool

сам пул в twisted.python.threadpool



Офлайн

#9 Май 8, 2008 16:14:39

van-gog
От:
Зарегистрирован: 2008-04-19
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

[q] Twisted

Андрей Светлов
:)
Ты должен просто ничего не делать.
реактор уже содержит пул потоков. С максимальным размером именно в 10 штук.
Поэтому просто бомби threads.deferToThread сколько хочешь раз. Больше десяти одновременно выполняться не будет.
sleep - тоже не нужен. У тебя реактор должен все время крутиться.

Код инициализации пула в twisted.internet.base:_initThreadPool

сам пул в twisted.python.threadpool
Спасибо, все заработало :)



Офлайн

#10 Май 14, 2008 18:47:43

van-gog
От:
Зарегистрирован: 2008-04-19
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

[q] Twisted

Здравствуйте еще раз :)
Теперь возник такой вопрос: как сделать чтоб ссылки, которые я передаю в threads.daferToThread скачивались через равное количество времени, н-р 1с. (ато сервер сильно грузит)
Зарание спасибо
ЗЫ: пробовал sleep - не реагирует



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version