Def stripnulls (data ): "The processing function of an empty string replaces all 00 bytes with null characters, and removes the empty strings before and after the condition" # Strip in Python is used to remove the first and last characters of a string. Similarly, lstrip is used to remove the characters on the left and rstrip is used to remove the characters on the right. Return data. replace ("\ 00", ""). strip () Class FileInfo (UserDict ): '''File base class, the file name of the stored file, inherited from UserDict (a class that stores key-value, you can override the _ setitem __,__ getitem _ method, You can use []) ''' # Self is used for definition and is not required for use. If there is no parameter, filename is set to None by default. If there is a parameter, It is filename. Def _ init _ (self, filename = None ): UserDict. _ init _ (self) # initialize the parent class Self ["name"] = filename # Set name To filaname Class MP3FileInfo (FileInfo ): "MP3 File Information Class, used to analyze MP3 file and storage information" # TagDataMap is used to store the location where the MP3 Tag information is located (key: Start location, end location, processing function ), # Stripnulls indicates the first defined function 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 MP3 files Self. clear () Try: Fsock = open (filename, "rb", 0) # open a file Try: # Set the pointer position for file reading. seek is the second parameter. 2 indicates that the position is used as a reference point from the end of the file, #-128 indicates that there are still points at the end of 128 bytes, 0 indicates that the start of the file is used as a reference point, and 1 indicates that the current position is used as a reference point. Fsock. seek (-128, 2) Tagdata = fsock. read (128) # read 128 bytes of data Finally: Fsock. close () # close the file. Note that in finally, you also need to close the file handle when an error occurs. If tagdata [: 3] = "TAG": # determine whether a Tag-containing MP3 file is valid # Cyclically retrieve Tag Information location information, such as 3, 33, stripnulls, and assign them to start, end, And parseFunc in sequence. For tag, (start, end, parseFunc) in self. tagDataMap. items (): # Tagdata [start: end] reads the byte from start to end and uses parseFunc to process the content Self [tag] = parseFunc (tagdata [start: end]) Handle t IOError: # If an IOError occurs, skip the next step. Pass # Override the _ setitem _ method. The above self [tag] = parseFunc (tagdata [start: end]) will use this method, # Key is tag, itme is parseFunc (tagdata [start: end]) Def _ setitem _ (self, key, item ): If key = "name" and item: # if key is name and item is not empty Self. _ parse (item) # parse MP3 files # Problem here, shoshould out of the if # FileInfo. _ setitem _ (self, key, item) If this indent is used, an error will occur. # Previous error points. Note the indentation here. The key-value will be stored in any case, and the FileInfo. _ setitem _ parent class method will be used for storage. FileInfo. _ setitem _ (self, key, item) Def listDirectory (directory, fileExtList ): "Obtain all fileExtList files in the directory. fileExtList is a list and can be in multiple formats" FileList = [OS. path. normcase (f) For f in OS. listdir (directory)] # list all directory files FileList = [OS. path. join (directory, f) For f in fileList # Filter files to meet a format in fileExtList. OS. path. splitext divides a file into file names and extensions. If OS. path. splitext (f) [1] in fileExtList] # Sys. modules [FileInfo. _ module _] obtain the FileInfo. _ module, where FileInfo. _ module _ is main, # If it is called by another module, it will not be. This is why "main" is not used directly" Def getFileInfoClass (filename, module = sys. modules [FileInfo. _ module _]): "Define a function to obtain file information" # Obtain the class to be parsed. If the mp3 file returns MP3FileInfo, the other is FileInfo. Subclass = "% sFileInfo" % OS. path. splitext (filename) [1]. upper () [1:] # Return a class. Note that a "class" is returned ". Use getattr to obtain the subclass class in the moudle Module Return hasattr (module, subclass) and getattr (module, subclass) or FileInfo # Note: This sentence may be difficult to understand. Why does getFileInfoClass (f) have two (f) Statements? As mentioned above, getFileInfoClass (f) # Return a parsing Class Based on the file name. Here the returned class is MP3FileInfo, and the second (f) indicates that the class is initialized with f MP3FileInfo (f) Return [getFileInfoClass (f) for f in fileList] If _ name _ = "_ main _": # main function. This code is not allowed in other modules. For info in listDirectory ("E: \ Music", [". mp3"]): # obtain information about all mp3 files in the E: \ Music folder cyclically # Because MP3FileInfo inherits from FileInfo and FileInfo inherits from UserDict, this items () is used to obtain the key-value set. # Format the output using "% s = % s" and use "\ n". join to concatenate all information with line breaks. Print "\ n". join (["% s = % s" % (k, v) for k, v in info. items ()]) Print # output a blank line after each file |