Skip to content

Instantly share code, notes, and snippets.

@velikodniy
Last active February 20, 2020 06:30
Show Gist options
  • Save velikodniy/6ce523263cb222832f6ca7954f7b587c to your computer and use it in GitHub Desktop.
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)
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())
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