|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 qiuyouzhi 于 2020-4-22 10:11 编辑
Python DEBUG 小技巧(1)
为什么要写这篇帖子?
因为论坛上的 "傻问题" 太多了!
光一个:
- list1 = [1,2,3,4,5]
- list2 = list1.reverse()
- print(list2)
复制代码
打印的结果为什么是None的问题,
就已经被问烂了!
本来,我试图搞一个Python FAQ,
结果发现根本没人看的。。。
(链接:https://fishc.com.cn/forum.php?m ... =view&ctid=1659)
我和痛心,同时,还发现一大批看报错信息就能知道的问题,
却还要发帖询问为什么。
所以,这就是这篇帖子的由来。
学会看报错信息
假设有这么一段代码:
大家是不是一眼就能看出来问题在哪里?
但是,如果改成这样:
- '''
- Function:
- 音乐下载器
- Author:
- Charles
- 微信公众号:
- Charles的皮卡丘
- '''
- import sys
- if __name__ == '__main__': from modules import *
- else: from .modules import *
- '''basic info'''
- BASICINFO = '''************************************************************
- Function: 音乐下载器 V2.1.2
- Author: Charles
- 微信公众号: Charles的皮卡丘
- 操作帮助:
- 输入r: 重新初始化程序(即返回主菜单)
- 输入q: 退出程序
- 下载多首歌曲: 选择想要下载的歌曲时,输入{1,2,5}可同时下载第1,2,5首歌
- 歌曲保存路径:
- 当前路径下的results文件夹内
- ************************************************************'''
- '''音乐下载器'''
- class musicdl():
- def __init__(self, configpath=None, config=None, **kwargs):
- self.config = loadConfig('config.json') if config is None else config
- self.logger_handle = Logger(self.config['logfilepath'])
- self.initializeAllSources()
- '''非开发人员外部调用'''
- def run(self, target_srcs=None):
- while True:
- print(BASICINFO)
- # 音乐搜索
- user_input = self.dealInput('请输入歌曲搜索的关键词: ')
- target_srcs = ['baiduFlac', 'kugou', 'kuwo', 'qq', 'qianqian', 'netease', 'migu', 'xiami', 'joox'] if target_srcs is None else target_srcs
- search_results = self.search(user_input, target_srcs)
- # 打印搜索结果
- title = ['序号', '歌手', '歌名', '大小', '时长', '专辑', '来源']
- items = []
- records = {}
- idx = 0
- for key, values in search_results.items():
- for value in values:
- items.append([str(idx), value['singers'], value['songname'], value['filesize'], value['duration'], value['album'], value['source']])
- records.update({str(idx): value})
- idx += 1
- printTable(title, items)
- # 音乐下载
- user_input = self.dealInput('请输入想要下载的音乐编号: ')
- need_download_numbers = user_input.split(',')
- songinfos = []
- for item in need_download_numbers:
- songinfo = records.get(item, '')
- if songinfo: songinfos.append(songinfo)
- self.download(songinfos)
- '''音乐搜索'''
- def search(self, keyword, target_srcs):
- search_results = {}
- if 'baiduFlac' in target_srcs:
- try:
- search_results.update({'baiduFlac': self.baiduFlac.search(keyword)})
- except:
- self.logger_handle.warning('无法在%s中搜索 ——> %s...' % ('baiduFlac', keyword))
- if 'kugou' in target_srcs:
- try:
- search_results.update({'kugou': self.kugou.search(keyword)})
- except:
- self.logger_handle.warning('无法在%s中搜索 ——> %s...' % ('kugou', keyword))
- if 'kuwo' in target_srcs:
- try:
- search_results.update({'kuwo': self.kuwo.search(keyword)})
- except:
- self.logger_handle.warning('无法在%s中搜索 ——> %s...' % ('kuwo', keyword))
- if 'netease' in target_srcs:
- try:
- search_results.update({'netease': self.netease.search(keyword)})
- except:
- self.logger_handle.warning('无法在%s中搜索 ——> %s...' % ('netease', keyword))
- if 'qianqian' in target_srcs:
- try:
- search_results.update({'qianqian': self.qianqian.search(keyword)})
- except:
- self.logger_handle.warning('无法在%s中搜索 ——> %s...' % ('qianqian', keyword))
- if 'qq' in target_srcs:
- try:
- search_results.update({'qq': self.qq.search(keyword)})
- except:
- self.logger_handle.warning('无法在%s中搜索 ——> %s...' % ('qq', keyword))
- if 'migu' in target_srcs:
- try:
- search_results.update({'migu': self.migu.search(keyword)})
- except:
- self.logger_handle.warning('无法在%s中搜索 ——> %s...' % ('migu', keyword))
- if 'xiami' in target_srcs:
- try:
- search_results.update({'xiami': self.xiami.search(keyword)})
- except:
- self.logger_handle.warning('无法在%s中搜索 ——> %s...' % ('xiami', keyword))
- if 'joox' in target_srcs:
- try:
- search_results.update({'joox': self.joox.search(keyword)})
- except:
- self.logger_handle.warning('无法在%s中搜索 ——> %s...' % ('joox', keyword))
- return search_results
- '''音乐下载'''
- def download(self, songinfo):
- for songinfo in songinfos:
- if songinfo['source'] == 'baiduFlac':
- self.baiduFlac.download([songinfo])
- elif songinfo['source'] == 'kugou':
- self.kugou.download([songinfo])
- elif songinfo['source'] == 'kuwo':
- self.kuwo.download([songinfo])
- elif songinfo['source'] == 'netease':
- self.netease.download([songinfo])
- elif songinfo['source'] == 'qianqian':
- self.qianqian.download([songinfo])
- elif songinfo['source'] == 'qq':
- self.qq.download([songinfo])
- elif songinfo['source'] == 'migu':
- self.migu.download([songinfo])
- elif songinfo['source'] == 'xiami':
- self.xiami.download([songinfo])
- elif songinfo['source'] == 'joox':
- self.joox.download([songinfo])
- '''run'''
- if __name__ == '__main__':
- dl_client = musicdl('config.json')
- dl_client.run()
复制代码
(感谢Charles未晞,这是TA的代码
这里由于篇幅问题,只展示部分代码)
你在不运行的情况下,是不是很难找到错误?
这时候,就体现报错信息的重要性了:
- Traceback (most recent call last):
- File "C:\Users\rzzl\Desktop\Music-Downloader-master\Music-Downloader-master\musicdl\musicdl.py", line 158, in <module>
- dl_client.run()
- File "C:\Users\rzzl\Desktop\Music-Downloader-master\Music-Downloader-master\musicdl\musicdl.py", line 60, in run
- self.download(songinfos)
- File "C:\Users\rzzl\Desktop\Music-Downloader-master\Music-Downloader-master\musicdl\musicdl.py", line 112, in download
- for songinfo in songinfos:
- NameError: name 'songinfos' is not defined
复制代码
(运行代码试试)
来分析报错信息:
1,看line,这是最有用的信息,它大多数都可以帮你定位到错误源。
2,看错误类型和错误信息,这是告诉你错误的详细内容。
可以发现,是112行的错误,直接翻到112:
- for songinfo in songinfos:
复制代码
发现这是整个函数的开头,于是错误就变得好找了很多,
songinfos是哪里来的呢?可以发现,是函数的一个参数。
- def download(self, songinfo):
复制代码
纳尼?这个参数怎么变成songinfo了?
赶紧改过来。
这时候再运行,发现没有问题了(这里鱼油
不需要自己尝试)。
这就是一次成功的DEBUG!
善用print()和DEBUG思想
有了print,你甚至可以不用调试功能!
(反正我是没有用过调试功能)
怎么做呢?
再拿一段代码例子:
- from requests import get
- from bs4 import BeautifulSoup as BS
- def open_url(url):
- headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400'}
- res = get(url,headers=headers)
- return res
- def get_MovieName(res):
- soup = BS(res.text, "html.parser")
- # 下面这段代码等同于soup.find_all()
- target = soup("div", class_='p12')
- for each in target:
- print(each.a.span.text)
- def main():
- url = 'https://movie.douban.com/chart'
- res = open_url(url)
- get_MovieName(res)
- if __name__ == "__main__":
- main()
复制代码
运行一下:
诶嘿?怎么什么都没有打印出来?
理论上是可以的啊?
这时候,我们就要分析一下
有可能错误的原因:
1,get()能不能抓取到数据?
2,find_all方法的class_有没有写错?
3,确定打印的是each.a.span.text?
这时候,就需要我们的print()了:
打印一下返回的数据:
OK,打印成功,大约有1600多行,
现在已经可以初步确定,get方法没有问题了。
但保险起见,还是展开看一下(防止是错误页面)
简单扫了扫,没有问题,证明这里是正确的。
然后看第二点,class_有没有写错?
翻源代码:
- <a class="nbg" href="https://movie.douban.com/subject/34805219/" title="饥饿站台">
- <img src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2566870171.webp" width="75" alt="饥饿站台" class=""/>
- </a>
- </td>
- <td valign="top">
-
- <div class="pl2">
- <a href="https://movie.douban.com/subject/34805219/" class="">
- 饥饿站台
- / <span style="font-size:13px;">饥饿斗室(港) / 绝命大平台(台)</span>
- </a>
复制代码
感觉并没有问题啊?
看看div的class,感觉是这里不对
把它复制过来:
我去,原来是pl(L)2,不是p12!
改过来之后,打印一下,成功了!
(第三点和第二点一起检查了)
3,打印所有错误类型
用这段代码:
- >>> for error in dir(__builtins__)[:72]:
- print(error)
复制代码
4.try-except大法
这个东西可以捕获所有(貌似有一个错误捕获不到)的错误,
比如这里有一个爬虫程序,程序里面有一个for循环,
只要运行这个程序就会报错(索引超出范围),
这时我们怎么做呢?
直接把这个for循环放进try里面,然后except的时候
退出循环。
P.S:获取报错信息可以:
- except Errortype as reason:
复制代码
当然,如果你想获取任何错误的报错信息(By zltzlt):
- except BaseException as reason:
复制代码
|
评分
-
查看全部评分
|