叙述起来有些麻烦,大致说一下:主程序中我开辟了进程池,然后我在其中一个进程中开辟个线程池,利用该线程池并发请求页面!但是,我发现线程池的分配必须写到函数中,如果写到外边当作全局变量的话,程序就一直卡在那里,不知道是阻塞了?还是无限的“递归”下去了?总之不出结果。
虽然我知道,线程池不能在主程序中分配好然后作为参数传给某个进程中使用,毕竟是进程嘛。一个道理,import的时候其实全局变量的线程池已经分配好了,然后你在进程中调用应该跟刚才说的是一个道理。我不明白的是为什么会一直运行....为什么不是报错?
代码贴在下边:
segmentfault不支持上传文件么??只能大家copy代码执行了。
主程序:开辟进程池,其中某个进程调用另一个文件的抓取方法,将url列表作为参数:
import json
import urllib_fetcher as ulib_fetch
#from multiprocessing.dummy import Pool as ThreadPool
from multiprocessing import Pool as ProcessPool
g_url_list = [
'http://segmentfault.com/q/1010000000742958',
'http://segmentfault.com/q/1010000003793646',
'http://segmentfault.com/q/1010000003757654',
'http://tieba.baidu.com/f?kw=%C4%E1%C2%EA&fr=ala0&tpl=5',
]
def main():
process_pool = ProcessPool(3)
ret = process_pool.apply_async(ulib_fetch.fetch, (g_url_list,))
process_pool.close()
process_pool.join()
print json.dumps(ret.get(), False, False)
if __name__ == "__main__":
main()
另一个抓取方法文件:urllib_fetcher.py
import sys
import urllib2 as ulib
from multiprocessing.dummy import Pool as ThreadPool
import socket
###########global var############
socket.setdefaulttimeout(5) # 设置全局的超时时间
thread_pool = ThreadPool(5) # ****全局线程池放到这里不行***
###########global var############
def unify_request(url):
"""
统一请求,失败的请求线程将返回None
"""
try:
res = ulib.urlopen(url)
except:
sys.stderr.write("urllib_fetcher failed for url: %s\n" % url)
return None
result = {
"url" : res.url,
"code" : res.code,
}
return result
def fetch(urls):
# thread_pool = ThreadPool(5) # 放到这里ok
try:
results = thread_pool.map(unify_request, urls)
except:
sys.stderr.write("fetch failed!\n")
return []
thread_pool.close()
thread_pool.join()
return results
多进程和多线程当然不一样,虽然 multiprocessing 为它们封装了形式基本一致的Pool接口,但Process和thread不能混为一谈。不同进程空间不共享变量,除非在共享内存上开辟。
全局的thread_pool、 g_url_list并不是一份,而是子进程从父进程fork出来后继承的一份独立副本, 在两个进程中各自修改并不互相影响。
但 fork 有个特性,在单线程状况复制内存数据到子进程,并不复制父进程的多线程状态。也就是说,即使子进程tread_pool对象有和父进程一样的数据,但不并存在ThreadPool(5)创建的5个线程。
至于为什么阻塞,我没看过multiprocessing的源码,猜想是根本等不到线程唤醒事件。
建议读APUE,注意thread and fork的章节,python的线程池进程池本质上都是对系统调用的封装组合。线程和进程没有像python里这些上层接口展现给你的这么简单,但如果从源码学习,反而C的代码更简单易理解。为了易用,multiprocessing 其实做了很多。