当前位置: 首页 > 编程日记 > 正文

Python程序员Debug利器,和Print说再见 | 技术头条

640?wx_fmt=jpeg


整理 | Rachel

责编 | Jane

出品 | Python大本营(id:pythonnews)


【导语】程序员每日都在和 debug 相伴。新手程序员需要学习的 debug 手段复杂多样,设置断点、查看变量值……一些网站还专门针对debug撰写了新手教程。老司机们在大型的项目中要 debug 的问题不一样,模块众多、代码超长,面对大型项目的debug之路道阻且长。针对新手和老手程序员会遇到的不同debug问题,本文推荐了两个GitHub上的开源debug工具:PySnooper 和 Behold,帮助大家更加优雅、简洁地 debug 代码。


前言


在之前的推荐中,营长为大家介绍过一些有趣的实用工具,包括自动化UI测试工具代码修复神器帮小白快速修复errorpdf翻译工具变量命名神器等等。今天,营长要为大家推荐两个基于 Python 的 debug 工具:PySnooper 和 Behold,帮助大家对不同规模的项目,有针对性的优雅 debug。


查看变量值,是 debug 过程中常要做的一件事。Python 开发者们除了使用 print 对变量逐个输出以外,是否还有其他方法可用呢?其实,使用 Print 语句查看变量有时候也很繁琐:首先需要找到变量所在的代码行,然后注释掉部分代码,再加一行输出命令;之后再根据原步骤进行复原。这波操作在代码量较大时就要耗费大量精力了,并且如果忘记复原,或者在复原代码时出现手误,甚至可能在 debug 过程中再新加 Bug,着实不值得!


此外,在一些大型项目上,我们有时只需要对项目的部分模块或代码行进行调试,但 Python 项目调试的时候需要人工对代码进行划分,以满足调试需求,这就使 debug 变得更困难。


为了让大家更专注写代码、debug 更轻松,营长特别选取了两个 Github 的 debug 神器:PySnooper 和 Behold,分别推荐给新手和大型代码项目的老司机。


接下来,先简单介绍并比较两个工具的特性,之后再具体讲解使用步骤、功能,如果想查看工具源代码和文档,可以到文末查看,别忘了给营长点”在看“!


PySnooper 与 Behold 对比:

对象不同,简洁相同


  • 使用对象不同


两个项目有何异同?两个作者对项目的描述就能轻松发现两者的不同:PySnooper——a poor man's debugger”,针对新手程序员;Behold——为大型Python项目专门搭建的 debug 工具。


  • 安装与使用


两个工具都不约而同地把“简便易用”作为了首要目标。PySnooper 和 Behold 都是一行代码搞定:”pip install“。使用上,两者对查看变量做了针对性地改进,都支持使用一行命令输出多个变量,不同于以往使用 print 语句的方式。


  • 特性


比较而言,PySnooper 更适用于调试单个函数,对函数变量的更改过程、指向操作所在代码行上更突出,可以对变量值及值发生改变时所对应的代码行进行输出,并将输出存储为文件。而 Behold 更加注重对代码的整体调试,以及 debug 时对变量的筛选,例如支持对全局变量和局部变量的区分等。


具体而言,PySnooper 的特性包括:


  • 输出关于某个函数中变量更改的详细过程记录,包括变量的值、使变量更改的相关代码行、更改时间

  • 将上述记录输出为一个.log文件

  • 查一个或多个非局部变量的值

  • 输出调试函数所引用的函数的变量更改记录

  • 在缓存中输出记录,提高运行速度


Behold 的特性包括:


  • 简单输出一个或多个变量的改变过程

  • 依据变量的值对输出进行条件筛选

  • 对变量的输出值给予自定义标签,提高输出结果的区分度

  • 依据调试变量所在函数的所属模块筛选是否输出变量值

  • 输出对象的部分或全部属性

  • 依据全局变量和局部变量对输出进行筛选

  • 将输出存储为Pandas.Dataframe格式的数据

  • 在输出时使用自定义字典对变量输出的值进行重新定义


PySnooper: 新手程序员救星


1.安装:使用pip


pip install pysnooper


2.设置需要调试的函数:使用@pysnooper.snoop()


import pysnooper
@pysnooper.snoop()def number_to_bits(number): if number: bits = [] while number: number, remainder = divmod(number, 2) bits.insert(0, remainder) return bits else: return [0]
number_to_bits(6)


输出如下:


Starting var:.. number = 621:14:32.099769 call         3 @pysnooper.snoop()21:14:32.099769 line         5     if number:21:14:32.099769 line         6         bits = []New var:....... bits = []21:14:32.099769 line         7         while number:21:14:32.099769 line         8             number, remainder = divmod(number, 2)New var:....... remainder = 0Modified var:.. number = 321:14:32.099769 line         9             bits.insert(0, remainder)Modified var:.. bits = [0]21:14:32.099769 line         7         while number:21:14:32.099769 line         8             number, remainder = divmod(number, 2)Modified var:.. number = 1Modified var:.. remainder = 121:14:32.099769 line         9             bits.insert(0, remainder)Modified var:.. bits = [1, 0]21:14:32.099769 line         7         while number:21:14:32.099769 line         8             number, remainder = divmod(number, 2)Modified var:.. number = 021:14:32.099769 line         9             bits.insert(0, remainder)Modified var:.. bits = [1, 1, 0]21:14:32.099769 line         7         while number:21:14:32.099769 line        10         return bits21:14:32.099769 return      10         return bits


3.将上述记录输出为文件,并保存在文件夹:文件命名为file.log,保存在“/my/log/”文件夹:


@pysnooper.snoop('/my/log/file.log')


4.查看一个或多个非局部变量的值:查看foo.bar, self.whatever变量的改变过程,这两个变量不在number_to_bits函数中


@pysnooper.snoop(variables=('foo.bar', 'self.whatever'))


5.输出调试函数所引用的函数的变量更改记录:


@pysnooper.snoop(depth=2)


6.在缓存中输出记录,提高运行速度:

@pysnooper.snoop(prefix='ZZZ ')


Beholder: 针对大型Python项目的调制工具


1.安装:使用pip


pip install behold


2.简单输出一个或多个变量的改变过程:


from behold import Behold
letters = ['a', 'b', 'c', 'd', 'A', 'B', 'C', 'D']
for index, letter in enumerate(letters): # 输出效果等价于如下代码 # print('index: {}, letter: {}'.format(index, letter)) Behold().show('index', 'letter')


3.依据变量的值对输出进行条件筛选:


from behold import Behold
letters = ['a', 'b', 'c', 'd', 'A', 'B', 'C', 'D']
for index, letter in enumerate(letters): # 输出效果等价于如下代码 # if letter.upper() == letter and index % 2 == 0: # print('index: {}'.format(index)) Behold().when(letter.upper() == letter and index % 2 == 0).show('index')


4.对变量的输出值给予自定义标签,提高输出结果的区分度:这里依据变量的值分别打“even_uppercase”和“odd_losercase”标签,附在变量之后


from behold import Behold
letters = ['a', 'b', 'c', 'd', 'A', 'B', 'C', 'D']
for index, letter in enumerate(letters): # 输出效果等价于如下代码 # if letter.upper() == letter and index % 2 == 0: # print('index: {}, letter:, {}, even_uppercase'.format(index, letter)) # if letter.upper() != letter and index % 2 != 0: # print('index: {}, letter: {} odd_lowercase'.format(index, letter)) Behold(tag='even_uppercase').when(letter.upper() == letter and index % 2 == 0).show('index', 'letter') Behold(tag='odd_lowercase').when(letter.lower() == letter and index % 2 != 0).show('index', 'letter')


5.依据调试变量所在函数的所属模块筛选是否输出变量值:


首先使用behold对函数设定调试规则:


from behold import Behold
# 这是一个在代码库中常用的自定义函数def my_function(): x = 'hello' # 这是函数本身的逻辑
# 在“testing”环境时输出x的值 Behold().when_context(what='testing').show('x')
# 仅在“debug”环境时对函数进行调试输出 if Behold().when_context(what='debugging').is_true(): import pdb; pdb.set_trace()


在另一个代码模块中对设定调试规则的函数进行调试:


from behold import in_context
# 设置context为“testing”@in_context(what='testing')def test_x(): my_function()test_x() # 将输出'x: hello'
# 使用环境管理器设置环境为“debugging”以进行调试with in_context(what='debugging'): my_function() # 转至pdb调试工具


6.输出对象的部分或全部属性:使用“with_args”指定调试对象的部分属性,使用“no_args”输出调试对象的全部属性


from behold import Behold, Item
item = Item(a=1, b=2, c=3)#输出对象的部分属性Behold(tag='with_args').show(item, 'a', 'b')#输出对象的全部属性Behold(tag='no_args').show(item)


7.依据全局变量和局部变量对输出进行筛选:


from __future__ import print_functionfrom behold import Behold, Item
# 定义全局变量g = 'global_content'
# 定义一个函数,设定局部变量def example_func(): employee = Item(name='Toby') boss = Item(employee=employee, name='Michael')
print('# Can\'t see global variable') Behold().show('boss', 'employee', 'g')
print('\n# I can see the the boss\'s name, but not employee name') Behold('no_employee_name').show(boss)
print('\n# Here is how to show global variables') Behold().show(global_g=g, boss=boss)
# 可以对变量的输出顺序进行调整 print('\n# You can force variable ordering by supplying string arguments') Behold().show('global_g', 'boss', global_g=g, boss=boss)
print('\n# And a similar strategy for nested attributes') Behold().show(employee_name=boss.employee.name)
example_func()


8.将输出存储为Pandas.Dataframe格式的数据:需要对变量值的标签进行定义,标签将存储为变量的键值


from __future__ import print_functionfrom pprint import pprintfrom behold import Behold, in_context, get_stash, clear_stash
def my_function(): out = [] for nn in range(5): x, y, z = nn, 2 * nn, 3 * nn out.append((x, y, z))
# 对变量值的标签进行定义
# 尽在测试x的环境下存储y和z的值 Behold(tag='test_x').when_context(what='test_x').stash('y', 'z')
# 仅在测试y的环境下存储x和z的值 Behold(tag='test_y').when_context(what='test_y').stash('x', 'z')
# 仅在测试z的环境下存储x和y的值 Behold(tag='test_z').when_context(what='test_z').stash('x', 'y') return out
@in_context(what='test_x')def test_x(): assert(sum([t[0] for t in my_function()]) == 10)
@in_context(what='test_y')def test_y(): assert(sum([t[1] for t in my_function()]) == 20)
@in_context(what='test_z')def test_z(): assert(sum([t[2] for t in my_function()]) == 30)
test_x()test_y()test_z()
print('\n# contents of test_x stash. Notice only y and z as expected')pprint(get_stash('test_x'))
print('\n# contents of test_y stash. Notice only x and z as expected')pprint(get_stash('test_y'))
print('\n# contents of test_z stash. Notice only x and y as expected')print(get_stash('test_z'))


也可以对存储的结果进行清除。


clear_stash()

当该命令的参数为空时,默认清除所有调试数据的缓存。如果想要指定清除某个或某些参数的调试缓存数据,则需在参数中进行指定。


9.在输出时使用自定义字典对变量输出的值进行重新定义:


下例中对变量的值进行了自定义。假设自定义字典中的键值为数据库索引,下例展示了将该索引转变为自定义标签的方法。


from __future__ import print_functionfrom behold import Behold, Item

# 定义Behold的子类以支持自定义的属性提取class CustomBehold(Behold): @classmethod def load_state(cls): cls.name_lookup = { 1: 'John', 2: 'Paul', 3: 'George', 4: 'Ringo' }
def extract(self, item, name): # 如果没有加载lookup state,则先进行加载 if not hasattr(self.__class__, 'name_lookup'): self.__class__.load_state()
# 抽取变量的值 val = getattr(item, name)
# 如果变量是一个Item类变量,则进行值转换 if isinstance(item, Item) and name == 'name': return self.__class__.name_lookup.get(val, None)
# 否则使用Behold默认的转换函数 else: return super(CustomBehold, self).extract(item, name)

# 定义一组Item变量用于测试items = [Item(name=nn) for nn in range(1, 5)]
print('\n# Show items using standard Behold class')for item in items: Behold().show(item)

print('\n# Show items using CustomBehold class with specialized extractor')for item in items:    CustomBehold().show(item, 'name''instrument')


总结


在本文中,营长针对新手程序员和 Python 大型项目的代码调试为大家分别推荐了PySnooper和Behold两个调试工具,帮助大家简化代码调试过程、优化调试输出,以提高代码调试效率,希望对大家有所帮助。在未来,营长也会继续努力为大家发掘更多好用的工具,帮助大家更优雅地书写代码。


PySnooper的Github地址:

https://github.com/cool-RR/PySnooper/tree/2c8c74903d20e0e52e358ce95af437a18f5fb495


Behold的Github地址:

https://github.com/robdmc/behold


(本文为Python大本营原创文章,转载请微信联系1092722531

长三角开发者联盟

代码就是力量,长三角的开发者联合起来!

加入「长三角开发者联盟」将获得以下权益

长三角地区明星企业内推岗位
CSDN独家技术与行业报告
CSDN线下活动优先参与权
CSDN线上分享活动优先参与权


扫码添加联盟小助手,回复关键词“长三角2”,加入「长三角开发者联盟」。

640?wx_fmt=jpeg

推荐阅读:

  • 机器学习萌新必备的三种优化算法 | 选型指南

  • A* 算法之父、人工智能先驱Nils Nilsson逝世 | 缅怀

  • Python程序员Debug的利器,和Print说再见 | 技术头条

  • 入门AI第一步,从安装环境Ubuntu+Anaconda开始教!

  • 小程序的侵权“生死局”

  • @996 程序员,ICU 你真的去不起!

  • Elastic Jeff Yoshimura:开源正在开启新一轮的创新 | 人物志

  • 19岁当老板, 20岁ICO失败, 21岁将项目挂到了eBay, 为何初创公司如此艰难?

  • 她说:为啥程序员都特想要机械键盘?这答案我服!

640?wx_fmt=png


点击阅读原文,了解CTA核心技术及应用峰会

相关文章:

【FFmpeg】解决警告warning: xxx is deprecated [-Wdeprecated-declarations]的方法

1、问题描述 编译FFmpeg程序时,经常报一些关于“deprecated”的警告信息,具体内容如下: decode.cpp:28:2: warning: ‘void av_register_all()’ is deprecated [-Wdeprecated-declarations]av_register_all(); decode.<

[BZOJ2527]Meteors

整体二分挺好玩的...学一发 这个询问显然是可以二分的&#xff0c;但每次都二分就会T爆&#xff0c;所以我们有了“整体”二分 每次处理一些询问&#xff0c;要求这些询问的答案一定在$[l,r]$中 先把$l$到$mid$的操作实施&#xff0c;那么当前TAK的询问答案一定在$[l,mid]$中&a…

一个可提供html5制作服务的网站

2019独角兽企业重金招聘Python工程师标准>>> 【TechWeb报道】最近网上出现了一个专门基于HTML5/CSS3制作服务的组织 P2H.cn. 就是专门提供网站切图的一项服务。特别在哪儿呢 &#xff0c;P2H.cn 可以制作出完美的兼容的html5/css3的页面。 王大利/文 如果你不知…

【Ubuntu】Ubuntu下的录频软件SimpleScreenRecorder

1、说明 官网介绍&#xff1a;https://www.maartenbaert.be/simplescreenrecorder/ 源码参见github&#xff1a;https://github.com/MaartenBaert/ssr 2、安装 Ubuntu版本>17.04&#xff0c;直接安装 sudo apt-get install simplescreenrecorderUbuntu版本<17.04&…

打开阿兹海默之门:华裔张复伦利用RNN成功解码脑电波,合成语音 | Nature

作者 | 琥珀出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;2019 年 4 月 24 日&#xff0c;来自加州大学旧金山分校&#xff08;UCSF&#xff09;神经外科学系 Gopala K. Anumanchipalli&#xff0c;Josh Chartier&#xff0c;Edward F. Chang 团队在 Nature 杂志上…

[转载] 别人的心得感悟

原文&#xff1a; https://www.cnblogs.com/double-K/p/6926367.html#commentform ---------------------------------------- 不可说的感悟-——十年老技术转型&#xff08;一&#xff09; 佛曰&#xff1a;“不可说&#xff0c;说既是错”&#xff0c;所以本篇也是错&#xf…

Windows Phone 7、XNA的旋转的背景

在游戏表现的过程中需要一些比较酷的动作&#xff0c;我们需要通过图型与XNA中的一些代码来实现&#xff0c;比如我们要说到的一个360度转动的圆。 在手机上的效果如下: 当然在这里我们看不到转动的效果&#xff0c;下边提供的有源码&#xff0c;大家可以下载运行测试一下。 操…

【Qt】报错error: undefined reference to `vtable for的解决方法

1、问题描述 编译Qt程序时&#xff0c;在某个类构造函数定义处报错&#xff1a; error: undefined reference to vtable for2、原因分析 导致错误信息的原因是&#xff1a;子类没有实现父类的纯虚函数&#xff1b; 在Qt中&#xff0c;首先要想到的是在一个类中添加了新的继承…

110万开发者的福音,百度Easy DL商品检测专业版上线

继首场百度大脑开放日上一口气开放24项全新AI技术后&#xff0c;4 月 25 日下午&#xff0c;第二期百度大脑开放日如约举行&#xff0c;本次共发布了13款AI通用新能力、5项技术升级&#xff0c;并推出了EasyDL商品检测专业版和语音识别自训练平台两大全新的可定制训练平台。 实…

简单爬虫学习记录

实现思路解析&#xff1a;爬虫调度器&#xff1a;启动/停止爬虫&#xff0c;规定爬虫的范围&#xff1b;URL管理器&#xff1a;管理2个URL&#xff1a;新的没有爬过的urls&#xff1b;旧的爬过的urls&#xff1b;URL下载器&#xff1a;下载url对应的html数据&#xff1b;HTML解…

开启笔记本win7的虚拟热点,让你的本本变成wifi

写在前面&#xff1a;相信很多人都跟我一样有困扰&#xff0c;在学校用校园网不能wifi&#xff0c;所以在此提供一个教程&#xff0c;希望能给机友们一些帮助。帖子转自网络&#xff0c;自己也测试过了。分享给大家&#xff0c;希望能给大家带来一些方便。开启windows 7的隐藏功…

检测到包降级: Microsoft.Extensions.Configuration.Abstractions 从 2.1.1 降 2.1.0

解决方法&#xff1a;工具-nuget管理包-程序管理控制台-选择 项目- 执行 -Install-Package Microsoft.Extensions.Configuration.Abstractions -Version 2.1.1命令即可。 转载于:https://www.cnblogs.com/dashanboke/p/9229826.html

【FFmpeg】如何通过url的格式找到对应的协议,以rtmp为例

1、简述 在使用 avio_open 接口时,只要给形参 filename 传入 url 格式的字符串就能找到对应的协议。这篇博客就是追踪 avio_open 的调用关系,探明如何根据一个url字符串就能找到对应的协议。下面以rtmp协议为例。 2、FFmpeg对rtmp协议的支持 rtmp协议的实现源码在 libavfo…

李开复口中的“联邦学习” 到底是什么?| 技术头条

近日&#xff0c;在百大人物峰会上&#xff0c;创新工场创始人李开复谈及数据隐私保护和监管问题时&#xff0c;表示&#xff1a;“人们不应该只将人工智能带来的隐私问题视为一个监管问题&#xff0c;可尝试用‘以子之矛攻己之盾’——用更好的技术解决技术带来的挑战&#xf…

业务逻辑应该在哪里实现更为合理呢?

请大牛们讨论下业务逻辑应该在哪实现较为合理 1、java业务逻辑层。 2、后台存储过程。 因为本人一直都在业务逻辑层实现。但新项目中领导要求将业务写到后台存储过程&#xff0c;java业务逻辑层不承载业务逻辑的实现功能。 先说本人的观点&#xff1a; 本人偏向写在java业务逻辑…

前端不哭!最新优化性能经验分享来啦 | 技术头条

作者 | Dimitris Kiriakakis译者 | 风车云马编辑 | Jane出品 | Python大本营&#xff08;id&#xff1a;pythonnews&#xff09;【导语】Angular、React、VueJS 是现在一些主流的 JS 框架&#xff0c;那它们在构建网站或前端程序时&#xff0c;是如何保证性能&#xff0c;减少大…

【FFmpeg】如何通过字符串到对应的封装器,以flv为例

1、简述 使用avformat_alloc_output_context2创建封装器上下文AVFormatContext时,只需将封装器的名字传递给形参format_name,就可以获取对应的封装器。这篇博客就是追寻avformat_alloc_output_context2的调用关系,探明原因。 函数原型如下: int avformat_alloc_output_co…

坚持使用Override 注解(36)

2019独角兽企业重金招聘Python工程师标准>>> 1、覆盖超类时千万小心&#xff0c;一不小心就变成重载了 2、现代的IDE 会在覆盖父类方法而没有使用Override 时给出一个警告 在具体类中不必标注你确信覆盖了的抽象方法声明的方法&#xff08;虽然这样做没什么不好&…

sql语句动态创建连接服务器

--建立连接服务器 EXEC sp_addlinkedserver --要创建的链接服务器名称 DMZLINK,--产品名称 MS,--OLE DB 字符 SQLOLEDB,--数据源 192.168.0.68 EXEC sp_addlinkedsrvlogin DMZLINK, false, NULL, --远程服务器的登陆用户名 sa, --远程服务器的登陆密码 sa go 转载于:h…

【FFmpeg】FFmpeg中操作目录、文件的接口

1、简述 在学习FFmpeg源码中的例子时,发现FFmpeg封装了操作目录和文件的接口。这篇博客把这些接口罗列出来,作为笔记简单记录下。 2、接口列表 打开目录,准备读取目录信息 int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options); 参数说明: u…

Scrapy爬取IT之家

创建项目 scrapy startproject ithome 创建CrawSpider scrapy genspider -t crawl IT ithome.com items.py 1 import scrapy 2 3 4 class IthomeItem(scrapy.Item): 5 # define the fields for your item here like: 6 # name scrapy.Field() 7 title scrapy.F…

高效读CV论文法则:先在GitHub上立Flag!| 资源

整理 | 琥珀出品 | AI科技大本营&#xff08;id&#xff1a;rgznai100&#xff09;今天介绍一份在 GitHub 上发现的最新干货资源——计算机视觉论文笔记&#xff0c;该项目是由一位名叫 ahong007007 的网友贡献的。该项目上线仅 20 天&#xff0c;尚未获得太多人的关注&#xf…

JS+CSS控制左右切换鼠标可控的无缝图片滚动代码

代码简介&#xff1a; 以前见过这种效果&#xff0c;但是是基于FLASH技术&#xff0c;现在是纯用JS实现的&#xff0c;代码有点多&#xff0c;不过效果还不错&#xff0c;实际上它也是一个图片滚动&#xff0c;只不过它完全是用鼠标点击控制的&#xff0c;也就是说鼠标不点击的…

【FFmpeg】自定义回调函数处理AVIOContext中的数据

1、简述 AVIOContext是FFmpeg管理输入输出数据的结构体,它的成员变量有指向数据的指针、大小以及处理数据的回调函数指针等等。如果使用avio_open或avio_open2来创建,它会根据指定的url协议,将协议处理数据的回调函数指针赋值给AVIOContext的相应成员变量。 我们也可以自己…

ZooKeeper系列(4):ZooKeeper的配置文件详解

ZooKeeper系列文章&#xff1a;https://www.cnblogs.com/f-ck-need-u/p/7576137.html#zk zkServer.sh读取的默认配置文件是$ZOOKEEPER_HOME/conf/zoo.cfg。如果要用其它配置文件。如下传递配置文件参数&#xff1a; zkServer.sh start your_config zkServer.sh stop your_co…

明星企业内推+BAT面经,长三角的开发者联合起来!

“为什么公司宁愿花20K招新人&#xff0c;也不愿给老员工加到20K&#xff1f;”这个热门的微博话题戳起了很多人的痛处&#xff0c;但根据 CSDN &《程序员》杂志发布的「中国软件开发者薪资调查报告」&#xff0c;有32.98%的开发者在过去曾换过工作&#xff0c;其中有72.5%…

《一江春水向东流》之随笔

这篇文章&#xff0c;更像是为后任正非时代的华为&#xff0c;进行的定调。开篇任总提到小时候的教育和意识养成的个人英雄主义&#xff0c;这种性格让自己四十岁之前遭遇坎坷。四十不惑之后&#xff0c;领悟了团结就是力量的政治内涵&#xff0c;开始妥协、包容。全篇浓墨重彩…

程序员拯救乐坛?OpenAI用“逆天”GPT2.0搞了个AI音乐生成器

作者 | 琥珀出品 | AI科技大本营&#xff08;id&#xff1a;rgznai100&#xff09;基于深度神经网络进行语音合成、音乐风格迁移&#xff0c;正成为不少致力于“让人人成为音乐家”的研究人员所追求的事情。像此前我们报道的微软小冰作词又作曲&#xff0c;AI帮清华博士写说唱歌…

centos7 JDK1.8

安装之前先检查一下系统有没有自带open-jdk rpm -qa |grep java rpm -qa |grep jdk 卸载找出的已安装Java相关rpm文件&#xff1a;rpm -e --nodeps 重新输入rpm -qa |grep java &#xff0c;卸载完成 下载jdk1.8 for linux的安装包 jdk-8u11-linux-x64.tar.gz&#xff0c;下载…

【FFmpeg】详解FFmpeg解封装、解码流程

目录 1、获取媒体信息头2、获取媒体流信息3、准备解码器3.1 获取视频、音频、字幕流在解封装上下文 AVFormatContext 的流列表 AVStream **streams 中的索引3.2 使用已经获取的流信息创建对应的解码器及其上下文,以视频解码器为例3.3 初始化解码器上下文4、准备用于保存解码前…