forked from codelucas/newspaper
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmthreading.py
More file actions
119 lines (98 loc) · 3.12 KB
/
Copy pathmthreading.py
File metadata and controls
119 lines (98 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# -*- coding: utf-8 -*-
"""
Anything that has to do with threading in this library
must be abstracted in this file. If we decide to do gevent
also, it will deserve its own gevent file.
"""
__title__ = 'newspaper'
__author__ = 'Lucas Ou-Yang'
__license__ = 'MIT'
__copyright__ = 'Copyright 2014, Lucas Ou-Yang'
import Queue
import traceback
from threading import Thread
class Worker(Thread):
"""
Thread executing tasks from a given tasks queue.
"""
def __init__(self, tasks):
Thread.__init__(self)
self.tasks = tasks
self.daemon = True
self.start()
def run(self):
while True:
try:
func, args, kargs = self.tasks.get()
except Queue.Empty:
traceback.print_exc()
break
try:
func(*args, **kargs)
except Exception:
traceback.print_exc()
self.tasks.task_done()
class ThreadPool:
"""
Pool of threads consuming tasks from a queue.
"""
def __init__(self, num_threads):
self.tasks = Queue.Queue(num_threads)
for _ in range(num_threads):
Worker(self.tasks)
def add_task(self, func, *args, **kargs):
"""
Add a task to the queue.
"""
self.tasks.put((func, args, kargs))
def wait_completion(self):
"""
Wait for completion of all the tasks in the queue.
"""
self.tasks.join()
def clear_threads(self):
"""
"""
pass
class NewsPool(object):
def __init__(self):
"""
Abstraction of a threadpool. A newspool can accept any number of
source OR article objects together in a list. It allocates one
thread to every source and then joins.
We allocate one thread per source to avoid rate limiting.
5 sources = 5 threads, one per source.
>>> import newspaper
>>> from newspaper import news_pool
>>> cnn_paper = newspaper.build('http://cnn.com')
>>> tc_paper = newspaper.build('http://techcrunch.com')
>>> espn_paper = newspaper.build('http://espn.com')
>>> papers = [cnn_paper, tc_paper, espn_paper]
>>> news_pool.set(papers)
>>> news_pool.join()
# All of your papers should have their articles html all populated now.
>>> cnn_paper.articles[50].html
u'<html>blahblah ... '
"""
self.papers = []
self.pool = None
def join(self):
"""
Runs the mtheading and returns when all threads have joined
resets the task.
"""
if self.pool is None:
print 'Call set(..) with a list of source objects before .join(..)'
raise
self.pool.wait_completion()
self.papers = []
self.pool = None
def set(self, paper_list, threads_per_source=1):
"""
Sets the job batch.
"""
self.papers = paper_list
num_threads = threads_per_source * len(self.papers)
self.pool = ThreadPool(num_threads)
for paper in self.papers:
self.pool.add_task(paper.download_articles)