2010-12-28 14 views
5

Ho uno script multi-thread che si blocca occasionalmente quando si collega a un server ma il server non invia nulla indietro. Netstat mostra una presa tcp collegata. Questo succede anche se ho impostato TIMEOUT. Il timeout funziona bene in uno script non leggibile. Ecco alcuni esempi di codice.pycurl/curl non seguendo l'opzione 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() 

Qualsiasi aiuto sarebbe molto apprezzato! ho cercato di risolvere questo problema per qualche settimana.

modifica: L'urllist ha circa 10 URL. Non sembra importare quanti ce ne sono.

edit2: Ho appena testato questo codice di seguito. Ho usato uno script php che dorme per 100 secondi.

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 in questo codice sembra scadere correttamente. Quindi immagino che abbia qualcosa a che fare con il numero di URL? GIL?

Edit3:

penso che potrebbe avere a che fare con libcurl stessa causa a volte quando controllo il libcurl script è ancora connesso a un server per ore e ore. Se pycurl fosse scaduto correttamente, la presa sarebbe stata chiusa.

+0

quanti URL sono in urllist quando si verifica questo problema? si verifica ancora con solo un singolo (o pochi) URL/thread? –

+0

se si avviano più thread utilizzando il proprio codice 'edit2', vengono eseguiti correttamente ogni timeout? –

+0

sì, funzionano bene. Ho provato con un paio di centinaia di thread generati e tutto è scaduto correttamente. – Incognito

risposta

3

ho modificato il codice 'edit2' per deporre le uova più thread e funziona bene sulla mia macchina (Ubuntu 10.10 con 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() 

Posso generare 100 thread e tutto il timeout a 3 secondi (come specificato).

non vorrei andare accusando ancora la contesa GIL e filo :)

1

I thread di Python sono ostacolati, in alcune situazioni, dal Global Interpreter Lock (il "GIL"). Può essere che i thread che stai iniziando non siano scaduti perché in realtà non vengono eseguiti abbastanza spesso.

Questo related StackOverflow question potrebbe puntare nella giusta direzione:

+0

da quello che ho capito il GIL interessa solo il codice Python. Ho capito pycurl semplicemente per consegnare tutto a libcurl e gestisce esso stesso il timeout. – Incognito

+0

Tuttavia, GIL influisce sul threading di Python. Controlla la domanda correlata. –

+0

alcuni URL hanno bisogno di cookie quindi non posso usare cookielib. Altrimenti mi sarei bloccato con urllib2. – Incognito

Problemi correlati