split optimize func in dedicated file
This commit is contained in:
		
							parent
							
								
									f5772f2783
								
							
						
					
					
						commit
						3a1c994b1e
					
				| @ -2,10 +2,9 @@ import argparse | ||||
| import logging | ||||
| import os | ||||
| import sys | ||||
| import time | ||||
| from concurrent.futures import ProcessPoolExecutor | ||||
| 
 | ||||
| from .files import Directory, FileGroup, FileImgMimetype, FileSizeRange | ||||
| from .files import Directory, FileImgMimetype, FileSizeRange | ||||
| from .optimizer import ImgOptimizer | ||||
| 
 | ||||
| DEFAULT_DEST_DIR = "data" | ||||
| 
 | ||||
| @ -109,32 +108,12 @@ def main(): | ||||
|         nb_workers, | ||||
|     ) | ||||
| 
 | ||||
|     start = time.perf_counter() | ||||
|     optimizer = ImgOptimizer(dest_dir, args.workers) | ||||
|     result = optimizer.optimize(fg) | ||||
|     (optimized, percent, size) = result.stats() | ||||
| 
 | ||||
|     with ProcessPoolExecutor(nb_workers) as p: | ||||
|         futures = [p.submit(f.opti, dest_dir) for f in fg.get_files()] | ||||
| 
 | ||||
|     fg_opti = FileGroup() | ||||
|     optimized = 0 | ||||
|     for f in futures: | ||||
|         if (res := f.result()) and res is not None: | ||||
|             match res: | ||||
|                 case (orig, None): | ||||
|                     logging.debug(f"no optimization for file: {orig}") | ||||
|                     fg_opti.add(orig) | ||||
|                 case (orig, opti): | ||||
|                     optimized += 1 | ||||
|                     logging.debug( | ||||
|                         f"optimization for file: {orig} -> {(1 - (opti.size / orig.size)) * 100:.2f}%"  # noqa | ||||
|                     ) | ||||
|                     fg_opti.add(opti) | ||||
| 
 | ||||
|     logging.info(f"optimization finished in {time.perf_counter() - start:.2f}s") | ||||
| 
 | ||||
|     percent = (1 - (fg_opti._size / fg._size)) * 100 | ||||
|     size_gained = fg._size - fg_opti._size | ||||
|     logging.info( | ||||
|         f"total optimization ({optimized}/{len(fg)}): {percent:.2f}% -> {size_gained:.2f} Mb"  # noqa | ||||
|         f"total optimization ({optimized}/{len(result.orig)}): {percent:.2f}% -> {size:.2f} Mb"  # noqa | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										88
									
								
								src/optimizer.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/optimizer.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | ||||
| import logging | ||||
| import os | ||||
| import subprocess | ||||
| import time | ||||
| from concurrent.futures import ProcessPoolExecutor | ||||
| from dataclasses import dataclass | ||||
| from typing import Optional | ||||
| 
 | ||||
| from .files import File, FileGroup, FileImgMimetype | ||||
| 
 | ||||
| 
 | ||||
| @dataclass(slots=True, frozen=True) | ||||
| class OptimizerResult: | ||||
|     orig: FileGroup | ||||
|     opti: FileGroup | ||||
|     optimized: int | ||||
| 
 | ||||
|     def stats(self) -> tuple[int, float, float]: | ||||
|         percent = (1 - (self.opti._size / self.orig._size)) * 100 | ||||
|         size = self.orig._size - self.opti._size | ||||
|         return (self.optimized, percent, size) | ||||
| 
 | ||||
| 
 | ||||
| @dataclass(slots=True, frozen=True) | ||||
| class ImgOptimizer: | ||||
|     dest_dir: str | ||||
|     nb_workers: int = 5 | ||||
| 
 | ||||
|     def _jpeg_optim(self, file: File) -> tuple["File", Optional["File"]] | None: | ||||
|         # remove ".." avoiding treat file in same dir | ||||
|         filepath = "/".join(file.path.split("/")[:-1]) | ||||
|         if filepath.startswith(".."): | ||||
|             filepath = filepath.lstrip("..") | ||||
| 
 | ||||
|         # replace all spaces in dir name for readability | ||||
|         dest_dir = os.path.join(self.dest_dir, filepath.lstrip("/")).replace(" ", "_") | ||||
|         os.makedirs(dest_dir, exist_ok=True) | ||||
| 
 | ||||
|         # use "-S <i>k" to set maximum size in kilobytes | ||||
|         cmd = f"jpegoptim -s -p -q -S 1024k '{file.path}' -d {dest_dir}" | ||||
|         logging.debug("optimization launched for file: %s -> %s", self, cmd) | ||||
|         try: | ||||
|             _ = subprocess.run(cmd, shell=True, check=True) | ||||
|         except subprocess.CalledProcessError as e: | ||||
|             logging.error("error while running command: %s, err: %s", cmd, e.output) | ||||
|             return None | ||||
|         except Exception: | ||||
|             logging.error( | ||||
|                 "unexpected error while running command: %s", cmd, exc_info=True | ||||
|             ) | ||||
|             return None | ||||
| 
 | ||||
|         try: | ||||
|             file_optim = File.from_directory(dest_dir, file.name) | ||||
|         except Exception as e: | ||||
|             logging.debug("unable to get file: %s after optimization: %s", file, e) | ||||
|             return file, None | ||||
| 
 | ||||
|         return file, file_optim | ||||
| 
 | ||||
|     def _optim(self, file: File) -> tuple["File", Optional["File"]] | None: | ||||
|         if file.mimetype == FileImgMimetype.JPEG.value: | ||||
|             return self._jpeg_optim(file) | ||||
|         return None | ||||
| 
 | ||||
|     def optimize(self, file_group: FileGroup) -> OptimizerResult: | ||||
|         start = time.perf_counter() | ||||
| 
 | ||||
|         with ProcessPoolExecutor(self.nb_workers) as p: | ||||
|             futures = [p.submit(self._optim, f) for f in file_group.get_files()] | ||||
| 
 | ||||
|         file_group_optim = FileGroup() | ||||
|         optimized = 0 | ||||
|         for f in futures: | ||||
|             if (res := f.result()) and res is not None: | ||||
|                 match res: | ||||
|                     case (orig, None): | ||||
|                         logging.debug(f"no optimization for file: {orig}") | ||||
|                         file_group_optim.add(orig) | ||||
|                     case (orig, opti): | ||||
|                         optimized += 1 | ||||
|                         logging.debug( | ||||
|                             f"optimization for file: {orig} -> {(1 - (opti.size / orig.size)) * 100:.2f}%"  # noqa | ||||
|                         ) | ||||
|                         file_group_optim.add(opti) | ||||
| 
 | ||||
|         logging.info(f"optimization finished in {time.perf_counter() - start:.2f}s") | ||||
|         return OptimizerResult(file_group, file_group_optim, optimized) | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 rmanach
						rmanach