日历

二月
28293031123
45678910
11121314151617
18192021222324
252627282912

分类

python 执行过程

2014年2月23日 16:17 | Comments(4) | Category:python | Tags:

参考资料

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,...' 字符串转换

 

代码执行过程

2014年2月23日 13:26 | Comments(1) | Category:python | Tags:

参考资料:

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

用户执行脚本,到达这里