鱼C论坛

 找回密码
 立即注册
查看: 1712|回复: 1

[新人报道] Python DEBUG 小技巧

[复制链接]
发表于 2020-4-9 18:09:54 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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

我和痛心,同时,还发现一大批看报错信息就能知道的问题,

却还要发帖询问为什么。

所以,这就是这篇帖子的由来。

学会看报错信息

假设有这么一段代码:
print("Hello World!"

大家是不是一眼就能看出来问题在哪里?

但是,如果改成这样:

'''
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()了:

打印一下返回的数据:
print(res.text)

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:

评分

参与人数 3荣誉 +9 鱼币 +11 贡献 +9 收起 理由
liuzhengyuan + 2 + 3 + 3 有创意
LYF511 + 5 + 5 + 3 鱼C有你更精彩^_^
zltzlt + 2 + 3 + 3 鱼C有你更精彩^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-4-9 18:47:19 | 显示全部楼层
没错~建议新手乐园发呀(他们只逛新手乐园,因为那里他们才能发帖)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-11 23:46

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表