按照手册实例结合自己想写的一个多访问的脚本,有了以下的代码.有 2 种写法的: 第 1 种速度快很多,但是出现多个 print 输出,实在想不出怎么冒出来的.是线程出错还是线程多余的.我开的 5 个线程,print(future_to_url) 对象也是 5 个.但是跑起来就多了出 3 个,而且文字还错乱了.
第 2 种暂时没有发现问题,求指教第一种为何会出现这种问题?
URLS = {'baidu':'http://www.baidu.com',
'sogou':'http://www.sogou.com',
'so':'http://www.so.com',
'youku':'http://www.youku.com',
'qq':'http://www.qq.com'
}
def load_url(s,args):
weburl = args['url']
if args['mark'] == 'baidu':
print(s + "百度访问:" + weburl)
rs = requests.get(weburl)
if args['mark'] == 'so':
print(s + "so:" + weburl)
rs = requests.get(weburl)
if args['mark'] == 'sogou':
print(s + "搜狗访问:" + weburl)
rs = requests.get(weburl)
if args['mark'] == 'qq':
print(s + "腾讯访问:" + weburl)
rs = requests.get(weburl)
if args['mark'] == 'youku':
print(s + "优酷访问:" + weburl)
rs = requests.get(weburl)
return str(rs.status_code)
title = '速度与激情'
conData ={'year':'2015','actor':'范·迪塞尔,保罗·沃克,杰森·斯坦森,米歇尔·罗德里格兹','subname':'狂野时速 7'}
aa = []
start = datetime.datetime.now()
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
# --------------------------------第 1 种.写法----------------------------------------------#
future_to_url = {executor.submit(load_url,title,conData): (conData['mark'] ,conData['url']) for conData['mark'],conData['url'] in URLS.items()}
print(future_to_url)
for future in concurrent.futures.as_completed(future_to_url):
url = future_to_url[future] #调用对应的 URL
try:
data = future.result() #获得函数返回的值
except Exception as exc:
print('%r generated an exception: %s' % (conData['url'], exc))#调试异常错误
else:
aa.append(data)
#--------------------------------第 2 种.写法----------------------------------------------#
# for conData['mark'],conData['url'] in URLS.items():
# future = executor.submit(load_url, title, conData)
# print(future)
# try:
# data = future.result() #获得函数返回的值
# except Exception as exc:
# print('%r generated an exception: %s' % (conData['url'], exc))#调试异常错误
# else:
# aa.append(data)
executor.shutdown(wait=True)
end = datetime.datetime.now()
print (end-start)
1
superrichman 2019-12-16 19:55:08 +08:00 1
|
2
GreenJoson OP @superrichman 谢谢大佬,但是这个结果可能不是我想要的.
URLS = {'baidu': ('http://www.baidu.com', '百度'), 这块 key 是为了识别,然后对应不同的网页规则,取不同的内容. 我只是示例一下.这个. title = '速度与激情' conData = {'year': '2015', 'actor': '范·迪塞尔,保罗·沃克,杰森·斯坦森,米歇尔·罗德里格兹', 'subname': '狂野时速 7'} 我之所以多了这一个,是因为这个字典变量是固定的,我需要加入这块字典去与获取的网址内容做对比. def load_url(s,args): weburl = args['url'] if args['mark'] == 'baidu': print(s + "百度访问:" + weburl) rs = requests.get(weburl) if args['mark'] == 'so': print(s + "so:" + weburl) rs = requests.get(weburl) if args['mark'] == 'sogou': print(s + "搜狗访问:" + weburl) rs = requests.get(weburl) if args['mark'] == 'qq': print(s + "腾讯访问:" + weburl) rs = requests.get(weburl) if args['mark'] == 'youku': print(s + "优酷访问:" + weburl) rs = requests.get(weburl) return str(rs.status_code) 这块主要是想判断不同的 mark 然后 get 不同的网站取相关内容. 可否告知我那个问题滥用的地方在哪里,谢谢~ |
3
ipwx 2019-12-16 20:18:40 +08:00 1
“for conData['mark'],conData['url'] in URLS.items():”
你不觉得这种用法很别扭么。。 ---- 首先,文字错乱是正常的。因为多线程,print 是同时执行的。你要保证 print 不错乱,得加锁,或者干脆收集到同一个线程里面去 print。 其次,我告诉你为啥会多出三项。就是因为你这个蹩脚的 for conData['mark'], conData['url']。说实话我很惊讶,因为我用 Python 这么多年,我都知不道 Python 能这么写。。。 从语义上看,这个写法的含义是把 URLS.items() 里面 for 出来的东西直接赋值到 conData 的这两个 entry 上面。 但是啊,少年,conData 只有一个哟,但你的线程有五个诶~ 所以你某个线程在执行某一个 if args['mark'] == 'xxx': 里面的 requests.get ,执行完以后,突然在下一个 if args['mark'] == 'yyy': 的时候,args['mark'] 就已经变化了,它发现又匹配了,就又执行了一遍。 |
4
GreenJoson OP @superrichman 然后做一些友善的提示,比如访问到哪个站点了...是否在线程里面不可以用 if 来判断?不然为何到最后多显示 3 条 print
|
5
ipwx 2019-12-16 20:20:27 +08:00
最后评论一下:我不明白你为什么会有搞一个全局对象做 for 循环调用函数传参对象的这么一个需求,不应该创建一个局部的临时变量做参数么。。。这才是你的 bug 根源,也是我这么多年没写过这种神奇代码的理由。
|
6
GreenJoson OP @ipwx 一语点破..谢谢你..“for conData['mark'],conData['url'] in URLS.items():” ,conData 只是为了加入一个字典里面,然后传递给函数,让函数去跟另一个字典做交集处理..哈哈..只是想偷懒而己.~
谢谢你,我知道问题所在了.~ |
7
ipwx 2019-12-16 20:22:27 +08:00
@GreenJoson 这种偷懒写法,随便重构一下就是一堆 bug 的根源。。。
|
8
ClericPy 2019-12-16 20:27:32 +08:00
for conData['mark'], conData['url'] in URLS.items() 这倒霉用法把我吓一跳...
建议多看看软件设计的原则那些东西, 不求全懂, 得会点常识, 至少把单一职责和高内聚低耦合做好. 祝早日写出让人读的赏心悦目的代码... |
9
GreenJoson OP |
10
ClericPy 2019-12-16 20:39:41 +08:00
@GreenJoson #9
我可不是大佬, 最近也在从头看设计模式, 自己写了太多屎山, 不过现在搜到的博客讲的都各说各有理... 大部分设计原则还是学设计模式时候里面捎带的, 我以前看的酷壳写的那个 https://coolshell.cn/articles/4535.html 不过比较旧. 要么就是随手翻的四人帮那个设计模式 虽说大部分人不看设计模式随着经验也能自发产生免疫力, 但是有这种捷径类疫苗在, 可以比较快地让自己知道自己哪里不优雅, 最后忠告就是别迷信设计模式 |
11
GreenJoson OP @ClericPy 谢谢你的忠告,我先看看你发的.感谢~
|