2010-12-28 2 views
5

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

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() 

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

Редактировать: Урлист имеет около 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 правильно выбрал время, розетка была бы закрыта.

+0

сколько URLs в urllist при возникновении этой проблемы? все еще происходит только с одним (или несколькими) URL-адресами/потоками? –

+0

, если вы запускаете несколько потоков, используя свой код «edit2», правильно ли они выполняются каждый раз? –

+0

Да, они отлично работают. Пробовал это с помощью пары сотен порожденных нитей, и все время было исправлено. – Incognito

ответ

3

Я изменил свой «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

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

Это related StackOverflow question может направить вас в правильном направлении:

+0

из того, что я понимаю, GIL влияет только на код python. Я понял pycurl просто, чтобы передать все на libcurl, и он сам справляется с таймаутом. – Incognito

+0

GIL действительно влияет на потоки Python. Проверьте соответствующий вопрос. –

+0

некоторые URL-адреса нужны куки, поэтому я не могу использовать cookielib. В противном случае я бы застрял с urllib2. – Incognito

Смежные вопросы