我正在写一个应该多次获取URL的小爬虫,我希望所有的线程同时运行(同时)。
我写了一段应该这样做的代码。
import thread
from urllib2 import Request, urlopen, URLError, HTTPError
def getPAGE(FetchAddress):
attempts = 0
while attempts < 2:
req = Request(FetchAddress, None)
try:
response = urlopen(req, timeout = 8) #fetching the url
print "fetched url %s" % FetchAddress
except HTTPError, e:
print 'The server didn\'t do the request.'
print 'Error code: ', str(e.code) + " address: " + FetchAddress
time.sleep(4)
attempts += 1
except URLError, e:
print 'Failed to reach the server.'
print 'Reason: ', str(e.reason) + " address: " + FetchAddress
time.sleep(4)
attempts += 1
except Exception, e:
print 'Something bad happened in gatPAGE.'
print 'Reason: ', str(e.reason) + " address: " + FetchAddress
time.sleep(4)
attempts += 1
else:
try:
return response.read()
except:
"there was an error with response.read()"
return None
return None
url = ("http://www.domain.com",)
for i in range(1,50):
thread.start_new_thread(getPAGE, url)
从apache日志来看,似乎线程并不是同时运行,请求之间有一点差距,它几乎检测不到但我可以看到线程并不是真正的并行。
我读过GIL,有没有办法绕过它而不需要调用C \ C ++代码? 我真的不明白GIL如何实现线程化? python基本上会在完成前一个线程时解释下一个线程吗?
感谢。
答案 0 :(得分:4)
正如您所指出的,GIL经常阻止Python线程并行运行。
然而,并非总是如此。 I / O绑定代码是一个例外。当一个线程正在等待I / O请求完成时,它通常会在进入等待之前释放GIL。这意味着其他线程可以在此期间取得进展。
但是,一般情况下,当需要真正的并行性时,multiprocessing
是更安全的选择。
答案 1 :(得分:1)
我读过关于GIL的内容,有没有办法绕过它而不调用C \ C ++代码?
不是真的。通过ctypes调用的函数将在这些调用期间释放GIL。执行阻塞I / O的函数也会释放它。还有其他类似的情况,但它们总是涉及主Python解释器循环之外的代码。你不能放弃Python代码中的GIL。
答案 2 :(得分:1)
您可以使用这样的方法创建所有线程,让它们等待条件对象,然后让它们开始获取URL“同时”:
#!/usr/bin/env python
import threading
import datetime
import urllib2
allgo = threading.Condition()
class ThreadClass(threading.Thread):
def run(self):
allgo.acquire()
allgo.wait()
allgo.release()
print "%s at %s\n" % (self.getName(), datetime.datetime.now())
url = urllib2.urlopen("http://www.ibm.com")
for i in range(50):
t = ThreadClass()
t.start()
allgo.acquire()
allgo.notify_all()
allgo.release()
这会让你更接近于同时发生所有提取,但是:
accept()
来回复您的请求。对于正确的行为,使用服务器全局锁实现,以确保只有一个服务器进程/线程响应您的查询。即使您的某些请求同时到达服务器,也会导致一些序列化。您可能会在更大程度上接受重叠的请求(即其他人在完成之前开始),但您永远不会得到所有同时启动的请求< / em>在服务器上。
答案 3 :(得分:0)
你也可以看看像pypy的未来,我们将拥有软件过渡记忆(从而废除GIL)这一切只是研究和知识分子嘲笑,但它可能会变成一个大的东西。
答案 4 :(得分:0)
如果您使用Jython或IronPython(以及未来的PyPy)运行代码,它将并行运行