0 pythonでfoobarのalternativeを作る 31

190620

DB更新 watchDog 対応

  • 画像処理の方に行ったつもりだったんだけど帰りの地下鉄でやり方が頭に浮かんできたので帰ってからやってみた
  • この機能が必要なのは、タグを修正するから
    私の膨大な音楽ファイルはタグも不統一で文字化けしてたり全くタグをつけてなかったり
    このアプリで見つけた都度少しづつ直してるが、それをすぐDBに反映させたいわけです
    今のDB作成ファイルだと対象フォルダの全スキャンから始まるので時間がかかる
    タグを書き換えた、変更したファイルだけ更新するようにすればほぼ一瞬で更新は終わります
    そのためのスクリプトということになる

database_dog.py

import  os ,mutagen 
import sqlite3

# update form dog_log

class makeDB():
    def __init__( self):
        self.fname=os.path.join(os.path.dirname(__file__) , 'watchdog.log')
        if not os.path.exists(self.fname):
            print('missing watchdog.log')
            input()
            quit()
        self.db=os.path.join(os.path.dirname(__file__) , 'database.db')
        if not os.path.exists(self.db):
            print('missing database.db')
            input()
            quit()
        conn = sqlite3.connect(self.db)
        c = conn.cursor()
        c.execute('create table IF NOT EXISTS musics(path PRIMARY KEY,mdate,flag,artist,album,title)')
        self.count={'new':0 , 'same':0,'mod':0, 'update':0 }
        self.first(c) # ログを開いてDBのチェック
        # quit()
        self.second(c) # フラグがNoneのものを更新
        c.execute('DELETE FROM musics WHERE flag=4') # フラグが4のものを削除
        
        c.close()
        conn.commit()
        conn.close()
        print(self.count)
        os.remove(self.fname)
        input('')
  
  
    def first(self,c):
        # フルパスをフラグNoneで新規挿入、成功したらそのまま
        # 失敗したらmdate比較して 同じならフラグ1 違ってたらフラグNone
        # フルパスが存在しなければFBから探してあったらフラグ4

        with open(self.fname,'r') as f:
            flist=f.readlines()
            flist_u = list(set(flist)) # リストにして重複行を削除
        # print(flist_u)

        for p in flist_u:
            p = p.replace('\n','')
            p = p.replace('\r','')
            # print('p',p)
            if os.path.exists(p):
                # print('f',p)
                mtime=os.path.getmtime(p)
                try:
                    c.execute( "INSERT INTO musics (path,mdate,flag) VALUES (?,?,?)" , (p,mtime,None ))
                    self.count['new']+=1
                except:
                    c.execute('select  mdate from musics where path = ?',(p, ))
                    res=c.fetchone()
                    if res :
                        if res[0]==mtime : # 同じなら flag=1
                            c.execute('update  musics set flag = ? where path = ? ',( 1, p ))
                            self.count['same']+=1
                        else : # 違ったら flag=None
                            c.execute('update  musics set mdate=?,flag = ? where path = ? ',( mtime,None, p ))
                            self.count['mod']+=1
            else : # でーた削除の場合
                c.execute('select  mdate from musics where path = ?',(p, ))
                res=c.fetchone()
                if res : # 存在したらフラグを4とする
                    c.execute('update  musics set flag = ? where path = ? ',( 4, p ))

    def second(self,c):
        c.execute('select path from musics where flag IS NULL')
        for p in  c.fetchall():
            # print(p)
            try:
                m = mutagen.File(p[0], easy=True) # m は辞書で要素はリスト、取り出し方が難しい
                tup=1,
            except:
                print('error-- ' + p[0])
                c.execute('update  musics set flag = ? where path = ? ',( 4, p[0] ))
                continue

            try:
                tup += m['albumartist'][0],
            except:
                try :
                    tup += m['artist'][0],
                except:
                    tup += '?',

            try :
                date=m['date'][0]
            except:
                date='?'
            try :
                album=m['album'][0]
            except:
                album='?'
            if date=='?' and album=='?' :
                tup += '?',
            else:
                tup += '['+ date + ']' + album ,

            title=''
            sl=''
            try :
                for i in m['discnumber'][0]:
                    if i == '/':
                        break
                    else:
                        sl += i
                title+='{:01}.'.format(int(sl))
            except:
                pass
            ti=''
            try:
                for i in m['tracknumber'][0]:
                    if i == '/':
                        break
                    else:
                        ti += i
                title+='{:02} '.format(int(ti))
            except:
                pass
            try:
                title += m['title'][0] 
            except:
                title='?'

            tup +=title,
            tup += p[0],
            c.execute('update musics set flag=?,artist=?,album=?,title=? where path=?' , tup )
            self.count['update']+=1

makeDB()
  • 基本的な設計は
    ①本体でwatcDogを実装、変更のあったファイルをログファイルに書き出す
    ②それをこのスクリプトで読み込んでDBを更新する
  • で、このスクリプトだが、基本はもとのDB作成ルーチンと同じ
    違いは、イテレータをglobの列挙ファイルとするか、logに列挙したファイルとするかだけ
    ただし細かい違いもあるので、もとのスクリプトとは別にすることにした、その方が安全だから
    コンソールだけど最後にログも表示するようにした
    本体からは別プロセスとして起動させる
  • 想定外だったのはwatcdogは同じファイルを何度か拾うこと
    理由はよくわからないが、ログには重複したファイルが含まれることになる
    で、一旦リストとして読み込んだ後、set()でユニークなリストにしてからイテレータとして使った
    もしかしたら重複したままでも問題ないかもしれないけどそれはsqlの仕様の問題も絡むからあえて実験していない
  • うまく動いてくれてます、かなりfoobarライク
    でもfoobarはもっとリアルタイムでライブラリに変更が反映される
    もう少し
    いつも思うけど、foobarはすごいよなあ

ツリーのコンテキストメニューでアルバムをリストに加えれるようにした

もとはドラッグオンリーだった
新しく書くのは面倒なのでドラッグを強引に偽装した
バギーかもしれない ( ̄― ̄?)


→ pythonでfoobarのalternativeを作る #

0

メモを他の人に見せる

このメモを見せたい人に、このURL(今開いているページのURLです)を教えてあげてください

コメント(0)

  • someone

  • someone