pycurl / curl不遵循CURLOPT_TIMEOUT选项

时间:2010-12-28 21:03:33

标签: python multithreading timeout pycurl

我有一个多线程脚本,当它连接到服务器但服务器不发回任何内容时偶尔会冻结。 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()

任何帮助将不胜感激!几个星期以来一直试图解决这个问题。

编辑: urllist有大约10个网址。似乎有多少并不重要。

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似乎正常超时。所以我猜它与网址的数量有关? GIL?

edit3:

我认为它可能与libcurl本身有关,因为有时当我检查脚本时libcurl仍然连续几个小时连接到服务器。如果pycurl正确地超时,则套接字将被关闭。

2 个答案:

答案 0 :(得分:3)

我修改了你的'edit2'代码以生成多个线程,它在我的机器上工作正常(Ubuntu 10.10 with 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 :(得分:1)

在某些情况下,Python线程被全局解释器锁(“GIL”)阻碍。可能是你正在启动的线程没有超时,因为它们实际上并没有经常运行。

related StackOverflow question可能会指向正确的方向: