こちらの質問の続きです.
※watchdogというフォルダ監視ができるライブラリを使用しています.
現在のコード
Python
1from watchdog.events import FileSystemEventHandler 2from watchdog.observers import Observer 3import os 4import time 5import zipfile 6import rarfile 7 8os.chdir(os.path.dirname(os.path.abspath(__file__))) 9rarfile.UNRAR_TOOL = os.getcwd()+r'\UnRAR.exe' 10 11if not os.path.exists("settings.ini"): 12 tmp=input("絶対パスで監視したいフォルダを指定してください(フォルダをDDすると楽)\n>>>") 13 if not os.path.exists(tmp): 14 print("そのディレクトリは存在していません") 15 exit() 16 17 with open("settings.ini",'w') as f: 18 f.write(tmp) 19 20with open("settings.ini",'r') as f: 21 target_dir = f.read() 22 23print('監視フォルダ:'+target_dir) 24 25class ChangeHandler(FileSystemEventHandler): 26 def on_created(self, event): 27 pass 28 29 def on_modified(self, event): 30 filepath = event.src_path 31 filename = os.path.basename(filepath) 32 33 if filepath[-4:]=='.zip' : 34 with zipfile.ZipFile(filepath) as zf: 35 zf.extractall(target_dir) 36 print('%sを解凍しました'% filename) 37 elif filepath[-4:]=='.rar' : 38 with rarfile.RarFile(filepath) as rf: 39 rf.extractall(target_dir) 40 print('%sを解凍しました'% filename) 41 else: 42 pass 43 44 def on_deleted(self, event): 45 filepath = event.src_path 46 filename = os.path.basename(filepath) 47 print('%sを削除しました' % filename) 48 49if __name__ in '__main__': 50 while 1: 51 event_handler = ChangeHandler() 52 observer = Observer() 53 observer.schedule(event_handler, target_dir, recursive=True) 54 observer.start() 55 try: 56 while True: 57 time.sleep(0.1) 58 except KeyboardInterrupt: 59 observer.stop() 60 observer.join()
注:前回の質問ではzipfile.is_zipfile(filepath):で判定をしてましたがこの場合だとzipファイル以外にも反応することがわかり,拡張子判定に切り替えています.
こちらを実行してzipファイルを投げますと,
Python
1line 34: with zipfile.ZipFile(filepath) as zf: 2PermissionError: [Errno 13] Permission denied: (filepath
のようにエラーが出ます.
PermissionErrorが出るということは, 複数のプロセスが何かしら同じファイルを対象にしていると考えてられるので, def on_modified(self, event):の挙動を調べようと思いました. else文をpassからprint("a")にして挙動を調べますと, 130kbの一つのファイルを投げ込んだだけでaが4回出力されたため, この関数は(ファイルのサイズにもよりますが)複数回起動しているみたいです.
つまり, 最初の
with zipfile.ZipFile(filepath) as zf: zf.extractall(target_dir)
の処理中にまたwith zipfile.ZipFile(filepath) as zf: が複数回起動しているため参照の重複が発生してエラーが出ていることがわかります.
つまり, ぱっと思いつく解決案としてはwith zipfile.ZipFile(filepath) as zf:が一回だけ作動するようにできればエラーは発生しなさそうですが, 何か妙案はないでしょうか...
※ちなみにdef on_created(self, event):はファイルが入った瞬間に起動するだけで,フォルダにファイルがコピー完了する前に反応してしまうため, こちらに解凍のコードを書いても実行することができません.
よろしくお願いします.
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。