コマンド引数として与えたパス内のサブディレクトリをそれぞれzip化し、元のサブディレクトリは削除するというスクリプトを書いています。
シングルスレッドの場合は問題なく動く(auto_zip()
)のですが、concurrent.futures.ThreadPoolExecutor()
を使いマルチスレッドで行う(auto_zip_multi_thread()
)と圧縮後のzipにいくつかのファイルが含まれていないことがあります。
ファイルの何割が抜けているのかは毎回異なり、同じディレクトリでも複数回実行すると毎回違う結果になります。
欠損なく処理が終わることもあります。
このように再現性がないのですが、どこをどう直せば良いのでしょうか?
zipを解凍し元のzipを削除する同じようなスクリプトは問題なく動くので、違いもよく分かりません。
python
1#!/usr/bin/env python3 2# auto_zip.py 3import argparse 4import concurrent.futures 5import pathlib 6import shutil 7 8 9# Lose data. 10def auto_zip_multi_thread(dirs: list[pathlib.Path]) -> None: 11 with concurrent.futures.ThreadPoolExecutor() as executor: 12 future_to_dir = {executor.submit(zip_and_remove_dir, i): i for i in dirs} 13 concurrent.futures.as_completed(future_to_dir) 14 15 16# Work fine and don't lose data. 17def auto_zip(dirs: list[pathlib.Path]) -> None: 18 for i in dirs: 19 zip_and_remove_dir(i) 20 21 22def zip_and_remove_dir(path: pathlib.Path) -> None: 23 shutil.make_archive(path, "zip", root_dir=path.parent, base_dir=path.name) 24 shutil.rmtree(path) 25 26 27def main(): 28 parser = argparse.ArgumentParser() 29 parser.add_argument("-p", "--path") 30 args = parser.parse_args() 31 path = pathlib.Path(args.path) 32 33 dirs = [i for i in path.iterdir() if i.is_dir()] 34 35 auto_zip(dirs) 36 # auto_zip_multi_thread(dirs) 37 38 39if __name__ == "__main__": 40 main() 41
#!/usr/bin/env python3 # auto_unzip.py import argparse import concurrent.futures import os import pathlib import zipfile def auto_unzip_multi_thread(zips: list[pathlib.Path]) -> None: with concurrent.futures.ThreadPoolExecutor() as executor: future_to_zip = {executor.submit(unzip_and_remove, z): z for z in zips} concurrent.futures.as_completed(future_to_zip) def unzip_and_remove(path: pathlib.Path) -> None: with zipfile.ZipFile(path) as existing_zip: existing_zip.extractall(os.path.splitext(path)[0]) os.remove(path) def main(): parser = argparse.ArgumentParser() parser.add_argument("-p", "--path") args = parser.parse_args() path = pathlib.Path(args.path) zip_files = [i for i in path.iterdir() if i.suffix[1:] == "zip"] auto_unzip_multi_thread(zip_files) if __name__ == "__main__": main()
回答1件
あなたの回答
tips
プレビュー