0

I want to use asyncio to get the size of a set of images.

Passing in a set of urls, I hope to get three values, (x, y, channel).

However, I cannot get anything.

Are there anythings wrong with my code?

from PIL import Image
from io import BytesIO
import numpy as np
import asyncio
import concurrent.futures
import requests

def get_image_shape(path):
    try:
        img = Image.open(BytesIO(requests.get(path).content))
        arr = np.array(img, dtype = np.uint8)
        return arr.shape
    except:
        return (0,0,0)

async def main(url_list):
    loop = asyncio.get_event_loop()
    futures = [
        loop.run_in_executor(
            None, 
            get_image_shape, 
            url
        )
        for url in url_list]
    for response in await asyncio.gather(*futures):
        pass

loop = asyncio.get_event_loop()
loop.run_until_complete(main(url_list))

#response.result()
#[(0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0)]
4
  • 2
    Maybe you shouldn't silence the exception raised. Commented May 25, 2018 at 9:26
  • So what should I change? Commented May 25, 2018 at 9:28
  • 2
    remove try/except so you can see what is happening - blanket suppression of exceptions like this is pretty bad style because it can hide a multitude of errors, as it is doing for you. Commented May 25, 2018 at 9:29
  • Thank you, barny. Commented May 25, 2018 at 9:47

1 Answer 1

3

Try this:

from PIL import Image
from io import BytesIO
import numpy as np
import asyncio
import concurrent.futures
import requests

def get_image_shape(path):
    try:
        img = Image.open(BytesIO(requests.get(path).content))
        arr = np.array(img, dtype = np.uint8)
        return arr.shape
    except:
        return (0,0,0)

async def main(url_list):
    loop = asyncio.get_event_loop()
    futures = [
        loop.run_in_executor(
            None, 
            get_image_shape, 
            url
        )
        for url in url_list]
    return [response for response in await asyncio.gather(*futures)]

loop = asyncio.get_event_loop()
response = loop.run_until_complete(main(url_list))
Sign up to request clarification or add additional context in comments.

5 Comments

Please consider removing the blanket try/except from the code in the answer. It is a Python antipattern which would be a good idea to avoid advertising.
What should we do for exception if removing the blanket try/except from the code?
@Mike You can let the exception propagate to the caller, so that they too get interrupted instead of continuing with some bogus value. Or, if you expect a particular operation to fail - for example, the file to be missing, then catch that exact exception, such as IOError. Catching any and all exceptions with except: is almost never what you want.
When we cannot be sure with what kind of exception happen, trying to catch all exception will play-safe.
Catching all exceptions and suppressing them is very risky, any unexpected exceptions that occur in your try block will also be suppressed and make it hard to find new errors. If you catch the specific exception you expect it limits that risk. Also, there are several actions in the try block, if the exception is expected from just one of them then only keep that in the try and move the rest to earlier or an else block. If you can't do these things you can at least log the exception at the error level so you still have the exception info when it occurs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.