pycurl / curl не следует параметру CURLOPT_TIMEOUT - PullRequest
5 голосов
/ 29 декабря 2010

У меня есть многопоточный скрипт, который иногда зависает при подключении к серверу, но сервер ничего не отправляет обратно. Netstat показывает подключенный TCP-сокет. Это происходит, даже если у меня установлен тайм-аут. Тайм-аут отлично работает в сценарии без резьбы. Вот пример кода.

def xmlscraper(url):
  htmlpage = StringIO.StringIO()
  rheader = StringIO.StringIO()
  c = pycurl.Curl()
  c.setopt(pycurl.USERAGENT, "user agent string")
  c.setopt(pycurl.CONNECTTIMEOUT, 60)
  c.setopt(pycurl.TIMEOUT, 120)
  c.setopt(pycurl.FOLLOWLOCATION, 1)
  c.setopt(pycurl.WRITEFUNCTION, htmlpage.write)
  c.setopt(pycurl.HEADERFUNCTION, rheader.write)
  c.setopt(pycurl.HTTPHEADER, ['Expect:'])
  c.setopt(pycurl.NOSIGNAL, 1)
  c.setopt(pycurl.URL, url)
  c.setopt(pycurl.HTTPGET, 1)

pycurl.global_init(pycurl.GLOBAL_ALL)
for url in urllist:
    t = threading.Thread(target=xmlscraper, args=(url,))
    t.start()

Любая помощь будет принята с благодарностью! пытался решить эту проблему уже несколько недель.

редактировать: У URL есть около 10 URL. Кажется, не имеет значения, сколько их.

edit2: Я только что проверил этот код ниже. Я использовал PHP-скрипт, который спит в течение 100 секунд.

import threading
import pycurl
def testf():
    c = pycurl.Curl()
    c.setopt(pycurl.CONNECTTIMEOUT, 3)
    c.setopt(pycurl.TIMEOUT, 6)
    c.setopt(pycurl.NOSIGNAL, 1)
    c.setopt(pycurl.URL, 'http://xxx.xxx.xxx.xxx/test.php')
    c.setopt(pycurl.HTTPGET, 1)
    c.perform()
t = threading.Thread(target=testf)
t.start()
t.join()

Pycurl в этом коде, по-видимому, правильно истекает. Так что я думаю, это как-то связано с количеством URL? GIL

edit3:

Я думаю, что это может быть связано с самой libcurl, потому что иногда, когда я проверяю сценарий, libcurl по-прежнему подключен к серверу в течение нескольких часов подряд. Если бы у pycurl было правильное время ожидания, сокет был бы закрыт.

Ответы [ 2 ]

3 голосов
/ 29 декабря 2010

Я изменил ваш код 'edit2' для создания нескольких потоков, и он отлично работает на моем компьютере (Ubuntu 10.10 с Python 2.6.6)

import threading
import pycurl

def testf():
    c = pycurl.Curl()
    c.setopt(pycurl.CONNECTTIMEOUT, 3)
    c.setopt(pycurl.TIMEOUT, 3)
    c.setopt(pycurl.NOSIGNAL, 1)
    c.setopt(pycurl.URL, 'http://localhost/cgi-bin/foo.py')
    c.setopt(pycurl.HTTPGET, 1)
    c.perform()

for i in range(100):
    t = threading.Thread(target=testf)
    t.start()

Я могу создать 100 потоков и все тайм-ауты за 3 секунды (как я указал).

Я бы пока не стал обвинять GIL и нить в споре:)

1 голос
/ 29 декабря 2010

Потоки Python, в некоторых случаях, блокируются Глобальной блокировкой интерпретатора («GIL»). Возможно, потоки, которые вы запускаете, не имеют времени ожидания, потому что на самом деле они запускаются недостаточно часто.

Этот связанный с StackOverflow вопрос может указать вам верное направление:

...