[英]running multiple threads in python, simultaneously - is it possible?
我正在編寫一個應該多次獲取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基本上解釋了下一個線程一旦完成前一個線程?
謝謝。
正如您所指出的,GIL經常阻止Python線程並行運行。
然而,情況並非總是如此。 I / O綁定代碼是一個例外。 當一個線程正在等待I / O請求完成時,它通常會在進入等待之前釋放GIL。 這意味着其他線程可以在此期間取得進展。
但是,一般而言,當需要真正的並行性時, multiprocessing
是更安全的選擇。
我讀過GIL,有沒有辦法繞過它而不用調用C \\ C ++代碼?
並不是的。 通過ctypes調用的函數將在這些調用期間釋放GIL。 執行阻塞I / O的函數也會釋放它。 還有其他類似的情況,但它們總是涉及主Python解釋器循環之外的代碼。 你不能放棄Python代碼中的GIL。
您可以使用這樣的方法來創建所有線程,讓它們等待條件對象,然后讓它們開始“ 同時 ”獲取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()
調用來響應您的請求。 對於正確的行為,使用服務器全局鎖實現,以確保只有一個服務器進程/線程響應您的查詢。 即使您的某些請求同時到達服務器,也會導致某些序列化。 您可能會在更大程度上獲得重疊請求(即其他人在完成之前開始),但您永遠不會在服務器上同時啟動所有請求。
如果您使用Jython或IronPython(以及未來的PyPy)運行代碼,它將並行運行
你還可以看看像pypy的未來,我們將擁有軟件過渡記憶(從而廢除GIL)這一切只是研究和知識分子嘲笑,但它可能會成長為一個大的東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.