2011-09-09 8 views
4

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) 

는 거의 탐지의 요청 사이에 약간의 차이가있어 보인다하지만 난 스레드가 정말 평행하지 않은 것을 볼 수 있습니다.

나는 GIL에 대해 읽었으며, C \ C++ 코드를 호출하지 않고 건너 뛸 수있는 방법이 있습니까? GIL을 사용하여 스레딩을 수행하는 방법을 실제로 이해할 수 없습니까? 파이썬은 기본적으로 이전 스레드와 끝나는 즉시 다음 스레드를 해석합니까?

감사합니다.

+0

에서 실행됩니다 것 urlopen하지 블록과 그 스레드가 병렬로 다운로드 의미? 서버를 소유하고 서버 측에서 인공 지연을 도입하여 3 초라고 말한 다음 스레드가 병렬로 시작하고 종료하는지 확인해야합니다. –

답변

4

GIL은 종종 Python 스레드가 병렬로 실행되는 것을 방지합니다.

그러나 항상 그런 것은 아닙니다. 한 가지 예외는 I/O 바인딩 된 코드입니다. 스레드가 I/O 요청이 완료되기를 기다리는 동안 일반적으로 대기 모드로 들어가기 전에 GIL을 릴리스합니다. 이것은 다른 스레드가 그 동안 진행을 할 수 있음을 의미합니다.

그러나 일반적으로 multiprocessing은 실제 병렬 처리가 필요할 때 더 안전합니다.

0

우리는 소프트웨어 이행 메모리가있는 pypy의 미래와 같은 것을 볼 수 있습니다. (따라서 GIL을 없애 버립니다.) 이것은 단지 모든 연구와 지적 scoffing 순간이지만 큰 무언가로 성장할 수 있습니다.

1

나는 GIL에 대해 읽었으며, C \ C++ 코드를 호출하지 않고 건너 뛸 수있는 방법이 있습니까?

아니요. ctypes를 통해 호출 된 함수는 해당 호출이 지속되는 동안 GIL을 해제합니다. 블로킹 I/O를 수행하는 함수도이를 해제합니다. 다른 비슷한 상황이 있지만 항상 파이썬 인터프리터의 메인 루프 외부에 코드가 포함됩니다. 파이썬 코드에서 GIL을 놓을 수는 없습니다.

당신은 모든 스레드를 만들려면이 같은 접근 방식을 사용할 수 있습니다
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() 

모든 페치가 동시에 발생 하지만있는에 가까운 비트 :

  • 컴퓨터를 떠나 네트워크 패킷이없는 동시에, 순서에 이더넷 와이어 함께 전달합니다,
  • 컴퓨터에 16 개 이상의 코어가 있더라도 시스템과 웹 호스트 사이에있는 일부 라우터, 브리지, 모뎀 또는 기타 장비가 코어 수가 적어 요청을 일련화할 수 있습니다.
  • 웹 서버 에서 물건을 가져 오면 accept() 전화를 사용하여 요청에 응답합니다. 올바른 동작을 위해 서버 전역 잠금을 사용하여 구현되어 하나의 서버 프로세스/스레드 만 쿼리에 응답하도록합니다.일부 요청이 서버 에 동시에 도달하더라도이 발생하면 일부 직렬화가 발생합니다.

당신은 아마 더 큰 정도 중복에 (일부 마무리하기 전에 시작 즉, 다른 사람을) 귀하의 요청을 얻을 것이다, 그러나 당신은 결코 서버에서 동시에시작으로 모든 요청을 얻을 않을 것입니다. 자이 썬 또는 IronPython의 (그리고 미래에 어쩌면 PyPy)와 코드를 실행하면

관련 문제