日历

二月
28293031123
45678910
11121314151617
18192021222324
252627282912

分类

代码执行过程

python 执行过程

奔斗 posted @ 2014年2月23日 16:17 in python , 1374 阅读

参考资料

Dive into python


在Dive into python第五章中有一个提取MP3信息的脚本,不是很理解现在整理一下思路

"""Framework for getting filetype-specific metadata.

Instantiate appropriate class with filename.  Returned object acts like a
dictionary, with key-value pairs for each piece of metadata.
    import fileinfo
    info = fileinfo.MP3FileInfo("/music/ap/mahadeva.mp3")
    print "\\n".join(["%s=%s" % (k, v) for k, v in info.items()])

Or use listDirectory function to get info on all files in a directory.
    for info in fileinfo.listDirectory("/music/ap/", [".mp3"]):
        ...

Framework can be extended by adding classes for particular file types, e.g.
HTMLFileInfo, MPGFileInfo, DOCFileInfo.  Each class is completely responsible for
parsing its files appropriately; see MP3FileInfo for example.

This program is part of "Dive Into Python", a free Python book for
experienced programmers.  Visit http://diveintopython.org/ for the
latest version.
"""

__author__ = "Mark Pilgrim (mark@diveintopython.org)"
__version__ = "$Revision: 1.3 $"
__date__ = "$Date: 2004/05/05 21:57:19 $"
__copyright__ = "Copyright (c) 2001 Mark Pilgrim"
__license__ = "Python"

import os
import sys
from UserDict import UserDict

def stripnulls(data):
    "strip whitespace and nulls"
    return data.replace("\00", " ").strip()

class FileInfo(UserDict):
    "store file metadata"
    def __init__(self, filename=None):
        UserDict.__init__(self)
        self["name"] = filename
    
class MP3FileInfo(FileInfo):
    "store ID3v1.0 MP3 tags"
    tagDataMap = {"title"   : (  3,  33, stripnulls),
                  "artist"  : ( 33,  63, stripnulls),
                  "album"   : ( 63,  93, stripnulls),
                  "year"    : ( 93,  97, stripnulls),
                  "comment" : ( 97, 126, stripnulls),
                  "genre"   : (127, 128, ord)}
    
    def __parse(self, filename):
        "parse ID3v1.0 tags from MP3 file"
        self.clear()
        try:
            fsock = open(filename, "rb", 0)
            try:
                fsock.seek(-128, 2)
                tagdata = fsock.read(128)
            finally:
                fsock.close()
            if tagdata[:3] == 'TAG':
                for tag, (start, end, parseFunc) in self.tagDataMap.items():
                    self[tag] = parseFunc(tagdata[start:end])
        except IOError:
            pass

    def __setitem__(self, key, item):
        if key == "name" and item:
            self.__parse(item)
        FileInfo.__setitem__(self, key, item)

def listDirectory(directory, fileExtList):
    "get list of file info objects for files of particular extensions"
    fileList = [os.path.normcase(f) for f in os.listdir(directory)]
    fileList = [os.path.join(directory, f) for f in fileList \
                if os.path.splitext(f)[1] in fileExtList]
    def getFileInfoClass(filename, module=sys.modules[FileInfo.__module__]):
        "get file info class from filename extension"
        subclass = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:]
        return hasattr(module, subclass) and getattr(module, subclass) or FileInfox
    return [getFileInfoClass(f)(f) for f in fileList]

if __name__ == "__main__":
    for info in listDirectory("/home/been/Desktop/", [".mp3"]):
        print "\n".join(["%s=%s" % (k, v) for k, v in info.items()])
        print

用户执行代码从这里开始

if __name__ == "__main__":
    for info in listDirectory("/home/been/Desktop/", [".mp3"]):

一个for循环代码跳到了自定义的function上

def listDirectory(directory, fileExtList):
    "get list of file info objects for files of particular extensions"
    fileList = [os.path.normcase(f) for f in os.listdir(directory)]
     """这里返回在目录directory下的所有文件,文件夹的小写名称到fielList"""
    fileList = [os.path.join(directory, f) for f in fileList \
                if os.path.splitext(f)[1] in fileExtList]
     """这里返回的是所有带地址的mp3格式的文件名,如/home/been/Desktop/wake me up.mp3"""
    def getFileInfoClass(filename, module=sys.modules[FileInfo.__module__]):
        "get file info class from filename extension"
        subclass = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:]
     """subclass 的内容是MP3FileInfo"""
        return hasattr(module, subclass) and getattr(module, subclass) or FileInfox
     """hastter()和getatter()是检查subclass这个模块是否可用,是就返回hasatter()否则返回FileInfo
        不过这里不仅仅是返回那么简单,同时还是调用了MP3FileInfo这个模块"""
    return [getFileInfoClass(f)(f) for f in fileList]

python执行代码到这里

class MP3FileInfo(FileInfo):
    "store ID3v1.0 MP3 tags"
    tagDataMap = {"title"   : (  3,  33, stripnulls),
                  "artist"  : ( 33,  63, stripnulls),
                  "album"   : ( 63,  93, stripnulls),
                  "year"    : ( 93,  97, stripnulls),
                  "comment" : ( 97, 126, stripnulls),
                  "genre"   : (127, 128, ord)}

MP3FileInfo从FileInfo中继承了它的方法,代码又跑到了这里

class FileInfo(UserDict):
    "store file metadata"
    def __init__(self, filename=None):
        UserDict.__init__(self)
        self["name"] = filename

同样FileInfo又从UserDict中继承了它的方法,UserDict是一个python自定义的class,用来创建字典的类。

可以用pydoc UserDict查看它的方法和属性。可以在/usr/lib/python2.7/UserDict.py 查看源代码

这部分代码生成了一个字典{filename:none}

接着代码回到了这里

class MP3FileInfo(FileInfo):
    "store ID3v1.0 MP3 tags"
    tagDataMap = {"title"   : (  3,  33, stripnulls),
                  "artist"  : ( 33,  63, stripnulls),
                  "album"   : ( 63,  93, stripnulls),
                  "year"    : ( 93,  97, stripnulls),
                  "comment" : ( 97, 126, stripnulls),
                  "genre"   : (127, 128, ord)}
    
    def __parse(self, filename):
        "parse ID3v1.0 tags from MP3 file"
        self.clear()
        try:
            fsock = open(filename, "rb", 0)
            try:
                fsock.seek(-128, 2)
                tagdata = fsock.read(128)
            finally:
                fsock.close()
            if tagdata[:3] == 'TAG':
                for tag, (start, end, parseFunc) in self.tagDataMap.items():
                    self[tag] = parseFunc(tagdata[start:end])
        except IOError:
            pass

    def __setitem__(self, key, item):
        if key == "name" and item:
            self.__parse(item)
        FileInfo.__setitem__(self, key, item)

在这里代码首先在__setitem__执行,疑问出来了书上说__setitem__是被MP3FileInfo覆盖的,但是__setitem__()却要和父类UserDict中的__setitem__()的参数的个数要一样。下面这两个是为了解决临界问题

当首次执行__setitem__时key为not defined,item在__parse已经创建。理解if这一句需要知道== and的优先顺序,这一句的意思是:如果key=="name"则执行self.__parse(item)否则执行File~。

因为FileInfo没有__setitem__类,因此需要到父类UserDict中去找。到这里所有的信息都存在了FileInfo字典中。

最后的代码

if __name__ == "__main__":
    for info in listDirectory("/home/been/Desktop/", [".mp3"]):
        print "\n".join(["%s=%s" % (k, v) for k, v in info.items()])
        print

for语句这里的info in ListDirectory(),相当于info=MP3FileInfo(),所以info有info.items()属性


后记:把博文写出来的确是对代码理解透彻了很多,因为只学过c,对类这种编程思想跟本没有了解过,一直在纠结干嘛要创建字典,是怎么通过类给字典里的key:value赋值,是怎么提取里面的元素的

补充python运算符的优先顺序:从上往下递增

运算符 描述
lambda Lambda表达式
or 布尔“或”
and 布尔“与”
not x 布尔“非”
in,not in 成员测试
is,is not 同一性测试
<,<=,>,>=,!=,== 比较
| 按位或
^ 按位异或
& 按位与
<<,>> 移位
+,- 加法与减法
*,/,% 乘法、除法与取余
+x,-x 正负号
~x 按位翻转
** 指数
x.attribute 属性参考
x[index] 下标
x[index:index] 寻址段
f(arguments...) 函数调用
(experession,...) 绑定或元组显示
[expression,...] 列表显示
{key:datum,...} 字典显示
'expression,...' 字符串转换

 

Avatar_small
依云 说:
2014年2月23日 17:12

有不少问题,特别是最后的运算符优先级,Python 的没有这么复杂。
对于执行顺序也不对,定义也是要被执行的,不然在后边会找不到名字。
参见 Python Language Reference。

Avatar_small
奔斗 说:
2014年2月23日 23:12

嗯!你说的对啊!的确有不少的问题,python的代码并不是想我写的那样从if __name__=__main__开始。我这里思考python代码的想法还是停留在c中,(只有一个主函数main(),主函数对其他函数的调用)。我在pdb上又跑了一下代码,的确是你说的那样顺序执行。哈哈关于那个运算符级别我是从a bit of python 上摘抄的。 不过那一句代码 if A==B and C 确实不是很明白

Avatar_small
依云 说:
2014年2月24日 20:18

pdb 没有 pudb 直观好用哦 =w=

if A==B and C 这是半个语句呀。

Avatar_small
AP 10th Science Ques 说:
2022年9月17日 02:13

AP 10th Class Science Model Paper 2023 Pdf Download may useful to both Telugu Medium, English Medium and Urdu Medium 10th class students of the state board to score better marks in the exams like SA-1, SA-2, FA-1, FA-2, FA-3, FA-4. AP 10th Science Question PaperThese practice model papers not only helped in getting marks but also improve the student’s knowledge of science.AP 10th Science Model Paper 2023 Pdf with answers suggested for all kinds of exams held under BSEAP along with assignments were made with the instructions of Leading educational institutes, Education portals of the state such as Sakshi Education, Eenadu Pratibha.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter