学习指导实践,实践验证学习,这个关系如果展开来说有着非常丰富的内涵。我目前有两种学习和实践方法层面的认知,即费曼的输出倒逼输入和最小必要知识,这种学习——实践——实践反馈学习——学习再指导实践的正向循环往复,对于塑造一个技能非常有用。二者是啥咱们暂且不表,但make your hands dirty,即积极实践的态度很关键。
比如咱们都知道Python这门语言,在科学计算和人工智能领域有广泛的应用。现在我要学它,应该怎么做?个人认为,首先要有一个积极的想去学习它的态度,make your hands dirty,那么我就会通过各种方法去搜集学习资料,了解这个语言的背景、应用领域、学习路线等整体性知识。其次,在一定基础之上,应该马上能用它解决问题。这里所谓的“一定基础”,可以是有其他语言基础,通过类比其他语言的特性和相通的编程思维,快速用Python开始从易到难地解决问题,“一定基础”需来自以前的学习和实践。所以年轻时学的那些知识为什么是必要的,因为如果你有能力在年轻时专门的时期内学的越好越多,以后会有更多的选择。最后,按照前面说的学习实践循环关系,不断深入和增强在这个领域的知识和技能。
初步的调试
使用搜索引擎,且互联网上的Python的语法和内置函数资料随手可得。然后我有一天下载了大量的目录结构相同的zip文件,结构如下:
文件1.zip
-- 文件1
-- 文件1.png
-- 文件1.jpg
-- 文件1.bmp
一个个点开解压缩很麻烦,于是想到可不可以用Python批量的解压缩?百度后,发现Python自己就有个zipfile模块,查Python官方文档,它有个extract方法可以用来解压缩。通过阅读官方文档,它的使用方法如下:
# 先构建ZipFile对象,只需用两个参数,mode只需用r
zipFile_obj = zipfile.ZipFile(zip_file_path, 'r')
我意识到自己作为一名初学者,没有能力一气呵成。于是我的想到的土方法是,用Python自带的IDLE,在命令行交互模式下逐句编写并测试,在这种模式下完成后,把其中有效的语句调整拼合成完整的py源程序代码。
现需要知道参数zip_file_path
,想到它是来自某目录下所有zip文件之一,要指定zip文件存放目录(用的windows),并从中取一个zip文件,因为是测试代码,不需要写循环取所有zip文件:
zip_dir_path = "d:/zip_dir/"
# 命令行模式下暂取一个zip文件
import os
zip_file = os.listdir(zip_dir_path)[0]
# zip_file_path是目录和文件名的合并
zip_file_path = os.path.join(zip_dir_path, zip_file)
有了zipFile_obj
对象,在文档里看下它的extract方法。extract有两个必选参数member,path
,member
可以是压缩包里的文件名或ZipInfo
对象,百度后发现一般可以用ZipFile
的namelist()
方法获取压缩包里的文件名,有机会可以了解什么情景下用ZipFile
对象,调用extract
方法代码如下:
# 还是不用循环取所有压缩包内文件,只取第一个
member = zipFile_obj.namelist()[0]
# extract第二个参数path还是用zip_dir_path,这个随意
zipFile_obj.extract(member, zip_dir_path)
到此,初步的调试已经做完了。
发现的若干问题
- 乱码问题
前面的操作基本比较顺利,但在调用extract
方法后我们却会发现解压出来的中文目录名和文件名是乱码。如下图:
百度后发现这是个zipfile的一个bug,并给出了解决办法,即先用cp437
encode
再用gbk
decode
:
member.encode('cp437').decode('gbk')
这种做法的大概原理是,你可以把字符串理解成一段数据,之所以有乱码,是因为member
在解压时是以cp437
编码的,系统不知道它是怎么编码的,就以默认编码显示,结果显示的是乱码。用了encode(437)
,这段数据就被还原成了正常数据,才可以再decode
为系统可正常显示的gbk
。
截止目前还不知道zipfile是不是有可以在解压后更正解压内容的方法,但能想到的可行办法是在解压缩后修改文件名,百度之后发现rename
可实现,如下:
os.rename(os.path.join(zip_dir_path,member),os.path.join(zip_dir_path,member.split('/')[-1].encode('cp437').decode('gbk'))
上面代码的意思是把member
里的文件重命名并移动到这个有所有zip文件夹下,rename
这个方法恰好还一同解决了目录问题,详见下面的说明。
- 目录问题
前面的extract
函数第一个参数member
如果用namelist
,namelist
里的元素可能是个目录,如上面目录结构的文件1
:
文件1.zip
-- 文件1
-- 文件1.png
-- 文件1.jpg
-- 文件1.bmp
如果有很多压缩文件,解压后就会文件1
、文件2
、文件3
...目录并列放在一起,但其实只想把其中的文件放在一起。
这时的想法是,每个文件解压后,再把它从这些目录中复制/剪切出来,恰好遇到rename
方法有这个功能。
此外,还可以看到目录路径我用的是/
,而不是\
,原因是\
在Python里是转义字符,如果改成\\
,虽然也能用,但在encode再decode时,会发生问题。具体是什么问题,请你自己敲代码测试。
完成完整的代码
(未完待更新)
后记:写下这篇东西的目的也是以教代学、输出倒逼输入的一次实践。