pythonでfoobarのalternativeを作る 6 190513 version 7
:追加された部分
:削除された部分
(差分が大きい場合、文字単位では表示しません)
自分のPCの音楽ファイルをタグでデータベース化 6
# 190513 の開発日記
pythonつかいづらい┐('д')┌
sqliteでdbいじるときは意図したとおりになっているか確認が必須だが、pythonだといちいち面倒
素だとselect文ですぐ結果表示されるはずなのにpythonはexecuteしたあとでfetchで取り出してprintしなくちゃイケない
で、sqlite のwin用exeを落とした
コンソールだけど簡単で、いいわ~( ´∀`)
アーカイブにはexeが三つ入ってるがとりあえず本体だけ解凍してdbのフォルダに置いたらすぐ使えた
当たり前だけど解説サイトの通りでselectしてやればすぐ結果がわかる
# コード
二段階方式の一段階目だけのコード書いてみた
新規時も更新時も使えるように
```
import sqlite3 , glob ,os ,time
# 更新の実験
conn = sqlite3.connect(r'e:\Programs\python\_研究\database\database.db')
c = conn.cursor()
sel='select mtime from musics where fullpath = ?'
fo=r'i:\Music\jazz\**'
count={'all':0 , 'file':0 , 'same':0 , 'diff':0 ,'none':0 , 'new':0}
start = time.time()
for p in glob.iglob(fo , recursive=True):
count['all'] += 1
if os.path.isfile(p):
count['file'] += 1
try:
c.execute( "INSERT INTO musics (fullpath) VALUES (?)" , (p, ))
count['new'] += 1
except:
c.execute('select mtime from musics where fullpath = ?',(p, ))
res=c.fetchone()
nmtime=os.path.getmtime(p)
if res :
if res[0]==nmtime :
count['same'] += 1
else :
count['diff'] += 1
print(p)
c.execute('update musics set mtime = ? where fullpath = ? ',( None, p ))
elapsed_time = time.time() - start
print ("elapsed_time:{0}".format(elapsed_time) + "[sec]")
print(count)
conn.commit()
conn.close()
```
- 重複チェックをtry文でエラー出させる方式にしたがこういうのは推奨されないのだろうか??最初にデータの存在有無をチェックしても良いんだけど
新規時はこの方が良いよな
更新時はほとんどがエラーではじかれるから何となく居心地悪い
- 新規時は重複がない前提だからまず挿入で良い。しかし更新時はある前提だから、挿入してエラーではじかせる過程が無駄って事か。重複してた場合にmtimeを取得して比較するプロセスは同じだ
- 新規時と重複時でコードを分けるか?コード自体は長くなるかもしれないけど優先すべきは速度だ。どうやって分岐させるか??
- やっぱり新規時は無視して更新時用のコード一本にするか。圧倒的に更新時の方が多いわけだし。一段階目は高速だから遅さもそんなに気にならないかもしれない。
- mtimeを二段階目に渡すフラッグにしようと思ってたけど二回取得することになるなら非効率だ。フラッグ用にnedrefresh みたいなカラムを作るか。
このフラグは基本は0。新規挿入時は1にする。更新時でmtimeが違っていたときも1に設定する。こうして第二段階に渡す。第二段階は1に対してタグ取得してデータ更新する、その時点でフラグを0に戻す
- このスキームならいらないんだが、当初mtimeをフラグにしようと思っていたときのtipsとして、NULLの扱いについて
**pythonでNULLに設定する場合は?にして'None'にする**
**NULLのチェックは、SELCT文でISNULLにする。**
**pythonでNULLに設定する場合は ? にして 'None' にする**
**NULLのチェックは、SELCT文で ISNULL にする。**
## mutagen調べた
Using Mutagen to process all accepted file types
https://stackoverflow.com/questions/19193551/using-mutagen-to-process-all-accepted-file-types
>>> m = mutagen.File(path, easy=True)
>>> m['title']
[u'Sunshine Smile']
>>> m['artist']
[u'Adorable']
>>> m['album']
[u'Against Perfection']
m = mutagen.File(path, easy=True)
m['title']
-->[u'Sunshine Smile']
m['artist']
-->[u'Adorable']
m['album']
-->[u'Against Perfection']
190513 の開発日記
pythonつかいづらい┐('д')┌
sqliteでdbいじるときは意図したとおりになっているか確認が必須だが、pythonだといちいち面倒
素だとselect文ですぐ結果表示されるはずなのにpythonはexecuteしたあとでfetchで取り出してprintしなくちゃイケない
で、sqlite のwin用exeを落とした
コンソールだけど簡単で、いいわ~( ´∀`)
アーカイブにはexeが三つ入ってるがとりあえず本体だけ解凍してdbのフォルダに置いたらすぐ使えた
当たり前だけど解説サイトの通りでselectしてやればすぐ結果がわかる
コード
二段階方式の一段階目だけのコード書いてみた
新規時も更新時も使えるように
import sqlite3 , glob ,os ,time
# 更新の実験
conn = sqlite3.connect(r'e:\Programs\python\_研究\database\database.db')
c = conn.cursor()
sel='select mtime from musics where fullpath = ?'
fo=r'i:\Music\jazz\**'
count={'all':0 , 'file':0 , 'same':0 , 'diff':0 ,'none':0 , 'new':0}
start = time.time()
for p in glob.iglob(fo , recursive=True):
count['all'] += 1
if os.path.isfile(p):
count['file'] += 1
try:
c.execute( "INSERT INTO musics (fullpath) VALUES (?)" , (p, ))
count['new'] += 1
except:
c.execute('select mtime from musics where fullpath = ?',(p, ))
res=c.fetchone()
nmtime=os.path.getmtime(p)
if res :
if res[0]==nmtime :
count['same'] += 1
else :
count['diff'] += 1
print(p)
c.execute('update musics set mtime = ? where fullpath = ? ',( None, p ))
elapsed_time = time.time() - start
print ("elapsed_time:{0}".format(elapsed_time) + "[sec]")
print(count)
conn.commit()
conn.close()
- 重複チェックをtry文でエラー出させる方式にしたがこういうのは推奨されないのだろうか??最初にデータの存在有無をチェックしても良いんだけど
新規時はこの方が良いよな
更新時はほとんどがエラーではじかれるから何となく居心地悪い - 新規時は重複がない前提だからまず挿入で良い。しかし更新時はある前提だから、挿入してエラーではじかせる過程が無駄って事か。重複してた場合にmtimeを取得して比較するプロセスは同じだ
- 新規時と重複時でコードを分けるか?コード自体は長くなるかもしれないけど優先すべきは速度だ。どうやって分岐させるか??
- やっぱり新規時は無視して更新時用のコード一本にするか。圧倒的に更新時の方が多いわけだし。一段階目は高速だから遅さもそんなに気にならないかもしれない。
- mtimeを二段階目に渡すフラッグにしようと思ってたけど二回取得することになるなら非効率だ。フラッグ用にnedrefresh みたいなカラムを作るか。
このフラグは基本は0。新規挿入時は1にする。更新時でmtimeが違っていたときも1に設定する。こうして第二段階に渡す。第二段階は1に対してタグ取得してデータ更新する、その時点でフラグを0に戻す - このスキームならいらないんだが、当初mtimeをフラグにしようと思っていたときのtipsとして、NULLの扱いについて
pythonでNULLに設定する場合は ? にして 'None' にする
NULLのチェックは、SELCT文で ISNULL にする。
mutagen調べた
Using Mutagen to process all accepted file types
https://stackoverflow.com/questions/19193551/using-mutagen-to-process-all-accepted-file-types
m = mutagen.File(path, easy=True)
m['title']
-->[u'Sunshine Smile']
m['artist']
-->[u'Adorable']
m['album']
-->[u'Against Perfection']