python多线程问题,非setDaemon,标志位控制,线程无法结束!

z752964360 z752964360 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
先看一个严重标志位是否好使的简单例子:

from threading import Thread,Lock
import time
a = True
class A:
def __init__(self,):
t = Thread(target=self.run)
t.start()
def run(self):
print 'im starting'
while a:
print a
if __name__ == "__main__":
aa=A()
time.sleep(1)
a= False

这个例子运行正常,说明可以通过标志位控制子线程。

下面这个是一个深度抓取页面的爬虫,提取出首页的所有链接继续抓这些链接的内容,,控制机制和上面例子一样。但是不能正常结束。

#coding=utf-8
from BeautifulSoup import BeautifulSoup
import urllib2
from threading import Thread,Lock
from Queue import Queue
import time
import socket
socket.setdefaulttimeout(5)

flag = True#标志位,控制子线程结束
class Fetcher:#封装的抓取网页的线程,处理结果的线程
def __init__(self,th_num):
self.opener = urllib2.build_opener(urllib2.HTTPHandler)
self.q_req = Queue() #任务队列
self.q_ans = Queue() #抓取结果处理队列
self.urls = []#返回下一深度要抓取的url
for i in range(th_num):#启动抓取线程
t = Thread(target=self.thread_get)
t.start()
for i in range(0,1):
t = Thread(target=self.thread_put)
t.start()


def join(self): #需等待两个队列完成
self.q_req.join()
self.q_ans.join()
print '=====================im done'#这个运行的时候也能打印出来。

def push(self,req):#往任务队列装任务
self.q_req.put(req)

def thread_put(self):#负责结果处理,将页面中的url存到sel.url里面
while flag:
print flag#调试用,如果这个线程没有结束,应该不断的打印flag才对
try:
url = self.q_ans.get()
self.urls.extend(url)
except Exception ,e:
print e,'other,excp========in=put'
finally:
self.q_ans.task_done()

def thread_get(self):
while flag:
print flag
try:
req = self.q_req.get()
urls = []
ans = self.opener.open(req).read()#抓取页面
soup = BeautifulSoup(ans)#解析页面
for a in soup.findAll('a'):#提取页面的所有链接
try:
if a['href'].startswith('http'):
urls.append(a['href'])
except Exception,ex:
print ex,'========================Exception=in=soup=findAll'
self.q_ans.put(urls)#将连接放入结果处理队列,让put线程去处理
except Exception, e:
print e,'other--exception----------in- threadget----'
finally:
print '--------------------'
self.q_req.task_done()
print "----------get---quiting"#这个看不到打印

def run(f,links):#作用是在下一轮抓取前清空urls,填装下一轮的任务,并等待任务完成。
f.urls = []
for url in links:
f.push(url)
f.join()
return f.urls

if __name__ == "__main__":
links = ['http://www.kingdowin.com/',]
deep = 2#要抓取的深度
f = Fetcher(10)
while deep > 0:#在这里结合run函数控制抓取深度
urls = run(f,links)
deep -= 1
links = urls
print len(links)

time.sleep(1)
flag = False #关闭线程
time.sleep(1)
print "Exiting Main Thread"#这一行会被打印出来
#每次运行,到这里,光标不动,通过任务管理器查看python的线程数13个
#线程虽然在,但不打印信息了

下面加上打印信息
Setting environment for using Microsoft Visual Studio 2008 x86 tools.

C:\Program Files\Microsoft Visual Studio 9.0\VC>G:

G:\>cd proxy

G:\proxy>python Quere.py
True
True
True
True
True
True
True
True
True
True
True
--------------------
True
True
=====================im done
17
--------------------
True
True
--------------------
True
True
--------------------
True
True
--------------------
True
True
--------------------
True
True
--------------------
True
True
--------------------
True
True
--------------------
True
True
--------------------
True
True
--------------------
True
True
--------------------
True
True
<urlopen error timed out> other--exception----------in- threadget----
--------------------
True
<urlopen error (11001, 'getaddrinfo failed')> other--exception----------in- thre
adget----
--------------------
True
--------------------
True
True
--------------------
True
True
--------------------
True
True
--------------------
True
True
=====================im done
195
Exiting Main Thread

#不能正常结束,如果标志位不起作用,应该不断打印true才对,但是没有。任务管理器里线程数还是10+
困惑,,,难道是Queue join的问题?但是=====================im done都打印出来了!

...全文

相关推荐

评论 18
收藏 已收藏
分享
返回顶部
z752964360
脚本语言 37,737 成员 34,208 内容