Last active
February 20, 2020 06:30
-
-
Save velikodniy/6ce523263cb222832f6ca7954f7b587c to your computer and use it in GitHub Desktop.
An example of converting images with asyncio/joblib (just an example, don't use in production)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import argparse | |
import asyncio | |
import time | |
from concurrent.futures.thread import ThreadPoolExecutor | |
from functools import partial | |
from pathlib import Path | |
import uvloop | |
from PIL import Image | |
thread_pool = ThreadPoolExecutor() | |
def load_and_resize(path, size): | |
image = Image.open(path) | |
image_resized = image.resize((size, size)) | |
image.close() | |
return image_resized | |
def save_image(image, path): | |
path.parent.mkdir(exist_ok=True, parents=True) | |
image.save(path) | |
async def process_image(image_path, size, output_format, output_dir): | |
loop = asyncio.get_event_loop() | |
image = await loop.run_in_executor( | |
thread_pool, | |
partial(load_and_resize, image_path, size) | |
) | |
output_path = output_dir / image_path.with_suffix(f'.{output_format}') | |
await loop.run_in_executor( | |
thread_pool, | |
partial(save_image, image, output_path) | |
) | |
def get_args(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument('input_dir', help='Input directory with JPEG files') | |
parser.add_argument('output_dir', help='Output directory for resized PNG files') | |
parser.add_argument('--size', default=1024, type=int, help='Output size') | |
parser.add_argument('--output-format', default='png', type=str, help='Output file format') | |
parser.add_argument('--input-format', default='jpg', type=str, help='Output file format') | |
return parser.parse_args() | |
async def main(): | |
args = get_args() | |
image_paths = list(Path(args.input_dir).rglob(f'*.{args.input_format}')) | |
output_dir = Path(args.output_dir) | |
output_dir.mkdir(exist_ok=True) | |
start_time = time.time() | |
tasks = [ | |
asyncio.create_task( | |
process_image(image_path, args.size, args.output_format, args.output_dir)) | |
for image_path in image_paths] | |
done, pending = await asyncio.wait(tasks) | |
assert len(pending) == 0 | |
elapsed_time = time.time() - start_time | |
print(f'Time: {elapsed_time:0.2f} s') | |
if __name__ == '__main__': | |
uvloop.install() | |
asyncio.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import argparse | |
import time | |
from pathlib import Path | |
import joblib | |
from PIL import Image | |
JOBLIB_BACKEND = 'threading' | |
def load_and_resize(path, size): | |
image = Image.open(path) | |
image_resized = image.resize((size, size)) | |
image.close() | |
return image_resized | |
def save_image(image, path): | |
path.parent.mkdir(exist_ok=True, parents=True) | |
image.save(path) | |
def process_image(image_path, size, output_format, output_dir): | |
image = load_and_resize(image_path, size) | |
output_path = output_dir / image_path.with_suffix(f'.{output_format}') | |
save_image(image, output_path) | |
def get_args(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument('input_dir', help='Input directory with JPEG files') | |
parser.add_argument('output_dir', help='Output directory for resized PNG files') | |
parser.add_argument('--size', default=1024, type=int, help='Output size') | |
parser.add_argument('--output-format', default='png', type=str, help='Output file format') | |
parser.add_argument('--input-format', default='jpg', type=str, help='Output file format') | |
return parser.parse_args() | |
def main(): | |
args = get_args() | |
image_paths = list(Path(args.input_dir).rglob(f'*.{args.input_format}')) | |
output_dir = Path(args.output_dir) | |
output_dir.mkdir(exist_ok=True) | |
start_time = time.time() | |
tasks = [ | |
joblib.delayed(process_image)(image_path, args.size, args.output_format, args.output_dir) | |
for image_path in image_paths] | |
joblib.Parallel(n_jobs=-1, backend=JOBLIB_BACKEND)(tasks) | |
elapsed_time = time.time() - start_time | |
print(f'Time: {elapsed_time:0.2f} s') | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment