2010-12-28 16 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() 

ご協力いただければ幸いです。今これを数週間解決しようとしています。

編集: urllistには約10のURLがあります。どれくらいあるかは関係ありません。

edit2: 次のコードをテストしました。私は100秒間スリープするPHPスクリプトを使用しました。

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

この問題が発生した場合、いくつのURLがurllistにありますか?それはまだ1つ(または少数)のURL /スレッドだけで起こりますか? –

+0

'edit2'コードを使用して複数のスレッドを開始する場合は、タイムアウトが正しく行われますか? –

+0

ええ、彼らは正常に動作します。数百の生まれのスレッドで試してみて、すべてタイムアウトしました。 – Incognito

答えて

3

、それは

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() 
(Pythonの2.6.6でのUbuntu 10.10)私のマシン上で正常に動作します

私は100スレッドを発生させることができ、すべてのタイムアウトは(指定したように)3秒で発生します。

GILとスレッドの競合を非難するつもりはありません:)

1

状況によっては、グローバルインタープリタロック(「GIL」)によってPythonスレッドがハングする場合があります。起動しているスレッドは、実際には頻繁に実行されていないため、タイムアウトしていない可能性があります。

このrelated StackOverflow question正しい方向にあなたを指している可能性があります:私は、複数のスレッドを生成するためにあなたの「EDIT2」コードを修正

+0

私はGILがPythonコードにしか影響しないと理解しています。私はpycurlを理解してlibcurlにすべてを渡すだけで、それ自体がタイムアウトを処理します。 – Incognito

+0

GILはPythonスレッドに影響します。関連する質問を確認してください。 –

+0

いくつかのURLにcookieが必要なので、cookielibは使用できません。そうでなければ、私はurllib2で立ち往生していたでしょう。 – Incognito

関連する問題