6

サーバーに接続するとフリーズすることがあるマルチスレッドスクリプトがありますが、サーバーは何も送り返しません。Netstatは、接続されたtcpソケットを示します。これは、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()

どんな助けでも大歓迎です!これを数週間解決しようとしています。

編集:URLリストには約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が適切にタイムアウトした場合、ソケットは閉じていたはずです。

4

2 に答える 2

3

'edit2'コードを変更して複数のスレッドを生成しましたが、私のマシンでは正常に動作します(Ubuntu10.10とPython2.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とスレッドの競合を非難するつもりはありません:)

于 2010-12-28T22:43:12.233 に答える
1

Pythonスレッドは、状況によっては、グローバルインタープリターロック(「GIL」)によって妨げられます。開始しているスレッドは、実際には十分な頻度で実行されていないため、タイムアウトしていない可能性があります。

この関連するStackOverflowの質問は、正しい方向を示している可能性があります。

于 2010-12-28T21:27:29.320 に答える