2017-12-27 31 views
2

ThreadPoolExecutorThread 클래스의 성능에 관한 질문이 있는데, 그것은 나 자신에게 몇 가지 근본적인 이해가 부족한 것처럼 보입니다.ThreadPoolExecutor 대 threading.Thread

저는 두 가지 기능으로 웹 조각 모음을했습니다. 구문 분석 링크 해제 이미지를로드하기 위해 웹 사이트 홈페이지와 두 번째의 각 이미지에 대한 링크를 구문 분석 할 수 첫째 :

다음 코드 두 건으로에서 분할
import threading 
import urllib.request 
from bs4 import BeautifulSoup as bs 
import os 
from concurrent.futures import ThreadPoolExecutor 

path = r'C:\Users\MyDocuments\Pythom\Networking\bbc_images_scraper_test' 
url = 'https://www.bbc.co.uk' 

# Function to parse link anchors for images 
def img_links_parser(url, links_list): 
    res = urllib.request.urlopen(url) 
    soup = bs(res,'lxml') 
    content = soup.findAll('div',{'class':'top-story__image'}) 

    for i in content: 
     try: 
      link = i.attrs['style'] 
      # Pulling the anchor from parentheses 
      link = link[link.find('(')+1 : link.find(')')] 
      # Putting the anchor in the list of links 
      links_list.append(link) 
     except: 
      # links might be under 'data-lazy' attribute w/o paranthesis 
      links_list.append(i.attrs['data-lazy']) 

# Function to load images from links 
def img_loader(base_url, links_list, path_location): 
    for link in links_list: 
     try: 
      # Pulling last element off the link which is name.jpg 
      file_name = link.split('/')[-1] 
      # Following the link and saving content in a given direcotory 
      urllib.request.urlretrieve(urllib.parse.urljoin(base_url, link), 
      os.path.join(path_location, file_name)) 
     except: 
      print('Error on {}'.format(urllib.parse.urljoin(base_url, link))) 

:

사례 1 : I

threads = [] 
t1 = threading.Thread(target = img_loader, args = (url, links[:10], path)) 
t2 = threading.Thread(target = img_loader, args = (url, links[10:20], path)) 
t3 = threading.Thread(target = img_loader, args = (url, links[20:30], path)) 
t4 = threading.Thread(target = img_loader, args = (url, links[30:40], path)) 
t5 = threading.Thread(target = img_loader, args = (url, links[40:50], path)) 
t6 = threading.Thread(target = img_loader, args = (url, links[50:], path)) 

threads.extend([t1,t2,t3,t4,t5,t6]) 
for t in threads: 
    t.start() 
for t in threads: 
    t.join() 

위 코드는 내 컴퓨터에서 10 초 동안 작업을 수행합니다.

사례 2 : 저는 18 초 ThreadPoolExecutor

with ThreadPoolExecutor(50) as exec: 
    results = exec.submit(img_loader, url, links, path) 

위 코드의 결과를 사용하고 있습니다.

제 생각에 ThreadPoolExecutor은 각 작업자를위한 스레드를 만듭니다. 그래서 max_workers을 50으로 설정하면 50 개의 스레드가 발생하므로 작업을 더 빨리 완료해야합니다.

누군가 내가 여기에없는 것을 설명해 주시겠습니까? 나는 여기서 어리석은 실수를 범하고 있음을 인정하지만 나는 그것을 얻지 못한다.

감사합니다.

+0

에서 단지 : 대신

exec.submit(img_loader, url, links, path) 

당신이 필요 했어. 그래서 나는 단지 하나의 링크를 받아들이도록 내'img_loader' 함수를 변경 한 다음 컨텍스트 관리자 아래에'for' 루프를 추가하여 목록의 각 링크를 처리했습니다. 그리고 그것은 3.8s로 시간을 감소 시켰습니다. – Vlad

답변

2

사례 2에서는 모든 링크를 한 명의 작업자에게 보냅니다. 나 자신을 그것을 밖으로 시도하지 않았다

for link in links: 
    exec.submit(img_loader, url, [link], path) 

@hansaplast 난 그냥 하나의 작업자를 사용하고 있었다 언급 한 바와 같이 그 reading the documentation of ThreadPoolExecutor

+1

네, 당신은 절대적으로 옳습니다. 나도 그걸 생각하고 있었지만 왜 나 자신을 시도하지 않았는 지 모르겠다. 나에게 다시 와줘서 고마워! 결과는 3.8 초로 멋지다! :) – Vlad