Python在操作前检测文件类型

时间:2015-08-20 00:11:10

标签: python if-statement flac mutagen

我处理this段代码,这个奇怪的错误出现在代码末尾附近的Try命令中。整个脚本针对.flac文件,有时它会读取文件夹中的.jpg文件并炸毁。很简单,我继续在if (".flac" or ".FLAC" in Song):之前添加Try,这样很容易就能处理正确的文件类型。然而,这完全没有区别,我继续得到以下错误

Traceback (most recent call last):
  File ".\musync.py", line 190, in <module>
    match_metadata(CurrentAlbum + Song, CoAlbum + Song)
  File ".\musync.py", line 152, in match_metadata
    TagSource = FLAC(SrcFile)
  File "C:\Python34\lib\site-packages\mutagen\_file.py", line 41, in __init__
    self.load(filename, *args, **kwargs)
  File "C:\Python34\lib\site-packages\mutagen\flac.py", line 721, in load
    self.__check_header(fileobj)
  File "C:\Python34\lib\site-packages\mutagen\flac.py", line 844, in __check_header
    "%r is not a valid FLAC file" % fileobj.name)
mutagen.flac.FLACNoHeaderError: 'C:/Users/berna/Desktop/Lib/Andrew Bird/Armchair Apocrypha/cover.jpg' is not a valid FLAC file

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File ".\musync.py", line 194, in <module>
    check_song(CurrentAlbum + Song, CoAlbum)
  File ".\musync.py", line 83, in check_song
    TagSource = FLAC(SrcFile)
  File "C:\Python34\lib\site-packages\mutagen\_file.py", line 41, in __init__
    self.load(filename, *args, **kwargs)
  File "C:\Python34\lib\site-packages\mutagen\flac.py", line 721, in load
    self.__check_header(fileobj)
  File "C:\Python34\lib\site-packages\mutagen\flac.py", line 844, in __check_header
    "%r is not a valid FLAC file" % fileobj.name)
mutagen.flac.FLACNoHeaderError: 'C:/Users/berna/Desktop/Lib/Andrew Bird/Armchair Apocrypha/cover.jpg' is not a valid FLAC file

为什么if条件没有做到这一点,我该如何解决这个问题?代码目前如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import shutil
import os

from mutagen.flac import FLAC  # Used for metadata handling.
from os import listdir  # Used for general operations.
from fuzzywuzzy import fuzz  # Last resource name association.
# Insert here the root directory of your library and device respectively.
lib = 'C:/Users/berna/Desktop/Lib/'
dev = 'C:/Users/berna/Desktop/Dev/'


# Faster file copying function, arguments go as follows: Source file location,
# target directory, whether to keep the filename intact and whether to create
# the target directory in case it doesn't exist.
def copy_file(SrcFile, TgtDir, KeepName=True, MakeDir=True):
    SourceFile = None
    TargetFile = None
    KeepGoing = False
    # Checks is TgtDir is valid and creates if needed.
    if MakeDir and not os.path.isdir(TgtDir):
        os.makedirs(TgtDir)
    # Processes TgtDir depending on filename choice.
    if KeepName is True:
        TgtDir += os.path.basename(SrcFile)
        print(TgtDir)
    try:
        SourceFile = open(SrcFile, 'rb')
        TargetFile = open(TgtDir, 'wb')
        KeepGoing = True
        Count = 0
        while KeepGoing:
            # Read blocks of size 2**20 = 1048576
            Buffer = SourceFile.read(2 ** 20)
            if not Buffer:
                break
            TargetFile.write(Buffer)
            Count += len(Buffer)
    finally:
        if TargetFile:
            TargetFile.close()
        if SourceFile:
            SourceFile.close()
    return KeepGoing


# XXX TODO
# Copies a directory (SrcDir) to TgtDir, if Replace is True will delete same
# name directory and replace with new one.
def copy_tree(SrcDir, TgtDir, Replace=True):
    if not os.path.isdir(TgtDir):
        os.makedirs(TgtDir)
    Target = format_dir(TgtDir, os.path.basename(SrcDir))
    if os.path.isdir(Target) and Replace:
        shutil.rmtree(Target)
    if not os.path.isdir(Target):
        os.makedirs(Target)
    for File in listdir(SrcDir):
        FileDir = format_dir(SrcDir, File)
        # copy_file(FileDir, Tgt)
    return()


# Checks for new and deleted folders and returns their name.
def check_folder(SrcDir, TgtDir):
    # Lists Source and Target folder.
    Source = listdir(SrcDir)
    Target = listdir(TgtDir)
    # Then creates a list of deprecated and new directories.
    Deleted = [FileName for FileName in Target if FileName not in Source]
    Added = [FileName for FileName in Source if FileName not in Target]
    # Returns both lists.
    return (Added, Deleted)


# Checks for song in case there's a name mismatch or missing file.
def check_song(SrcFile, TgtDir):
    Matches = []
    # Invariably the new name will be that of the source file, the issue here
    # is finding which song is the correct one.
    NewName = TgtDir + '/' + os.path.basename(SrcFile)
    TagSource = FLAC(SrcFile)
    # Grabs the number of samples in the original file.
    SourceSamples = TagSource.info.total_samples
    # Checks if any song has a matching sample number and if true appends the
    # song's filename to Matches[]
    for Song in listdir(TgtDir):
        SongInfo = FLAC(TgtDir + '/' + Song)
        if (SongInfo.info.total_samples == SourceSamples):
            Matches.append(Song)
    # If two songs have the same sample rate (44100Hz for CDs) and the same
    # length it matches them to the source by filename similarity.
    if (Matches.count > 1):
        Diffs = []
        for Song in Matches:
            Diffs.append(fuzz.ratio(Song, os.path.basename(SrcFile)))
        if (max(Diffs) > 0.8):
            BestMatch = TgtDir + '/' + Matches[Diffs.index(max(Diffs))]
            os.rename(BestMatch, NewName)
        else:
            shutil.copy(SrcFile, TgtDir)
    # If there's no match at all simply copy over the missing file.
    elif (Matches.count == 0):
        shutil.copy(SrcFile, TgtDir)
    # If a single match is found the filename will be the first item on the
    # Matches[] list.
    else:
        os.rename(TgtDir + '/' + Matches[0], NewName)


# Syncs folders in a directory and return the change count.
def sync(SrcDir, TgtDir):
    AddCount = 0
    DeleteCount = 0
    # Grabs the folders to be added and deleted.
    NewDir, OldDir = check_folder(SrcDir, TgtDir)
    # Checks if any and then does add/rm.
    if OldDir:
        for Folder in OldDir:
            shutil.rmtree(TgtDir + Folder)
            DeleteCount += 1
    if NewDir:
        for Folder in NewDir:
            shutil.copytree(SrcDir + Folder, TgtDir + Folder)
            AddCount += 1
    return(AddCount, DeleteCount)


# Fixes missing metadata fields.
def fix_metadata(SrcFile, TgtFile):
    TagSource = FLAC(TgtFile)
    TagTarget = FLAC(SrcFile)
    # Checks for deleted tags on source file and deletes them from target.
    if (set(TagTarget) - set(TagSource)):
        OldTags = list(set(TagTarget) - set(TagSource))
        for Tag in OldTags:
            # TODO Right now I haven't quite figured out how to delete
            # specific tags, so workaround is to delete them all.
            TagTarget.delete()
    # Checks for new tags on source file and transfers them to target.
    if (set(TagSource) != set(TagTarget)):
        NewTags = list(set(TagSource) - set(TagTarget))
        for Tag in NewTags:
            TagTarget["%s" % Tag] = TagSource[Tag]
            TagTarget.save(TgtFile)


# Does metadata transfer between two files.
def match_metadata(SrcFile, TgtFile):
    Altered = 0
    TagSource = FLAC(SrcFile)
    TagTarget = FLAC(TgtFile)
    # For every different Tag in source song copy it to target and save.
    for Tag in TagSource:
        if TagSource[Tag] != TagTarget[Tag]:
            Altered += 1
            TagTarget[Tag] = TagSource[Tag]
            TagTarget.save(TgtFile)
    return(Altered)


# Simply does directory formatting to make things easier.
def format_dir(Main, Second, Third=""):
    # Replaces \ with /
    Main = Main.replace('\\', '/')
    # Adds a / to the end of Main and concatenates Main and Second.
    if(Main[len(Main) - 1] != '/'):
        Main += '/'
    Main += Second + '/'
    # Concatenates Main and Third if necessary.
    if (Third):
        Main += Third + '/'
    return (Main)

# Sync main folders in lib with dev.
sync(lib, dev)
# For every Artist in lib sync it's Albums
for Artist in listdir(lib):
    sync(format_dir(lib, Artist), format_dir(dev, Artist))
    # For every Album in Artist match songs
    for Album in listdir(format_dir(lib, Artist)):
        # Declares lib Album and dev Album to make function calls shorter.
        CurrentAlbum = format_dir(lib, Artist, Album)
        CoAlbum = format_dir(dev, Artist, Album)
        for Song in listdir(CurrentAlbum):
            if (".flac" or ".FLAC" in Song):
                try:
                    # Tries to match lib and dev song's metadata.
                    match_metadata(CurrentAlbum + Song, CoAlbum + Song)
                except:
                    # If that fails will try to fix both Filename and Tag
                    # fields.
                    check_song(CurrentAlbum + Song, CoAlbum)
                    fix_metadata(CurrentAlbum + Song, CoAlbum + Song)
                    try:
                        # Try again after fix.
                        match_metadata(CurrentAlbum + Song, CoAlbum + Song)
                    except Exception as e:
                        # If it still doesn't work there's black magic in place
                        # go sleep, drink a beer and try again later.
                        print("""Ehm, something happened and your sync failed.\n
                              Error:{}""".format(e))
                        raise SystemExit(0)

2 个答案:

答案 0 :(得分:0)

试一试:

Songs = ["a.flac", "a.mp3", "b.FLAC"]
flac_files = [s for s in Songs if s.lower().endswith('.flac')]

答案 1 :(得分:0)

正如@EliKorvigo指出的那样,错误是由if条件中的简单错误引起的,修复看起来如下:

for Song in listdir(CurrentAlbum):
    if (".flac" in Song or ".FLAC" in Song):
        try:
            # Tries to match lib and dev song's metadata.
            match_metadata(CurrentAlbum + Song, CoAlbum + Song)
        except:
            # If that fails will try to fix both Filename and Tag
            # fields.
            check_song(CurrentAlbum + Song, CoAlbum)
            fix_metadata(CurrentAlbum + Song, CoAlbum + Song)
            try:
                # Try again after fix.
                match_metadata(CurrentAlbum + Song, CoAlbum + Song)
            except Exception as e:
                # If it still doesn't work there's black magic in place
                # go sleep, drink a beer and try again later.
                print("""Ehm, something happened and your sync failed.\n
                      Error:{}""".format(e))
                raise SystemExit(0)