我对理解python多处理没什么问题。我写了一个应用程序,巫婆分析下载的网页。我想在具有特定超时的单独进程中获取原始html。我知道我可以在urllib2中设置超时,但在某些情况下使用socks5代理时似乎无法正常工作。 所以,写了一个小类:
class SubprocessManager(Logger):
def __init__(self, function):
self.request_queue = Queue()
self.return_queue = Queue()
self.worker = function
self.args = ()
self.kwargs = {'request_queue': self.request_queue,
'return_queue': self.return_queue}
self._run()
def _run(self):
self.subprocess = Process(target=self.worker, args=self.args, kwargs=self.kwargs)
self.subprocess.start()
def put_in_queue(self, data):
self.request_queue.put(data)
def get_from_queue(self):
result = None
try:
result = self.request_queue.get(timeout=10)
except Empty:
self.reset_process()
return result
def reset_process(self):
if self.subprocess.is_alive():
self.subprocess.terminate()
self._run()
工人职能:
def subprocess_fetch_www(*args, **kwargs):
request_queue = kwargs['request_queue']
return_queue = kwargs['return_queue']
while True:
request_data = request_queue.get()
if request_data:
return_data = fetch_request(*request_data)
return_queue.put(return_data)
从输入列表为每个URL调用的函数:
def fetch_html(url, max_retry=cfg.URLLIB_MAX_RETRY, to_xml=False, com_headers=False):
subprocess = Logger.SUBPROCESS
args = (url, max_retry, com_headers)
subprocess.put_in_queue(args)
result = subprocess.get_from_queue()
if result and to_xml:
return html2lxml(result)
return result
我需要帮助修复我的代码。我希望我的子进程一直在运行,等待request_queue中的作业。我想只在超时的情况下重新创建子进程。一旦处理了request_data并将return_data放入返回队列,Worker就应该暂停执行。
我如何实现这一目标?
编辑:
好吧,如果get_from_queue
请求return_queue
的结果数据而不是request_queue
...> _>'
答案 0 :(得分:1)
好的,我想我对你想做的事情有了更好的理解。
看看这段代码。这不是OO,但说明了这个想法。
from multiprocessing import Process, Queue, Pipe
from time import sleep
import random
proc = None
inq = None
outq = None
def createWorker():
global inq, outq, proc
inq = Queue()
outq = Queue()
proc = Process(target=worker, args=(inq,outq))
proc.start()
def worker(inq, outq):
print "Worker started"
while True:
url = inq.get()
secs = random.randint(1,5)
print "processing", url, " sleeping for", secs
sleep(secs)
outq.put(url + " done")
def callWithTimeout(arg):
global proc, inq, outq
inq.put(arg)
result = None
while result is None:
try:
result = outq.get(timeout=4)
except:
print "restarting worker process"
proc.terminate()
createWorker()
inq.put(arg)
return result
def main():
global proc, inq, outq
createWorker()
for arg in ["foo", "bar", "baz", "quux"]:
res = callWithTimeout(arg)
print "res =", res
proc.terminate()
main()
它使用两个队列 - 一个用于向工作进程发送消息,另一个用于接收结果。你也可以使用管道。此外,重新启动工作进程时会创建新队列 - 这是为了避免可能的竞争条件。
编辑:刚刚看到你的编辑 - 看起来是一样的想法。