I'm working with matplotlib.pyplot
and Azure Storage blobs (azure.storage.blob
) in a Azure Functions environment (should not access the file system).
My goal is to get a blob:
service = blob.BlobServiceClient(account_url="https://mysa.blob.core.windows.net", credential=SA_PRIMARY_KEY)
blob_client = service.get_blob_client(container="mycontainer", blob="myimg.JPG")
blob_data = blob_client.download_blob()
And open it with pyplot using imread
like:
img = plt.imread(blob_data_to_read_opened_stream, format="JPG")
So I think I'm missing a piece. After obtaining the blob_data
object it's needed to copy it's content into a stream passing it to pyplot
with open("./BlockDestination.jpg", "wb") as blob_stream:
blob_data = blob.download_blob()
blob_data.readinto(blob_stream)
img = plt.imread(blob_stream, format="JPG")
This would fail cause imread needs a
file-like object opened in read-binary mode
How can I achieve my goal without opening two different streams?
You can generate a SAS token and use it to read images from your storage account directly instead of download images and read them. It will ease the server pressure and only one read stream here. Just try the code below:
from azure.storage.blob import ResourceTypes, AccountSasPermissions, generate_account_sas,BlobServiceClient
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.cbook as cbook
connStr = '<storage account connection string>'
containerName ='<container name>'
blobName = "<image name>"
blob_service_client = BlobServiceClient.from_connection_string(connStr)
sas_token = generate_account_sas(
blob_service_client.account_name,
account_key=blob_service_client.credential.account_key,
resource_types=ResourceTypes(object=True),
permission=AccountSasPermissions(read=True),
expiry=datetime.utcnow() + timedelta(hours=1)
)
destImageUrl = blob_service_client.primary_endpoint + containerName + "/" + blobName + "?" + sas_token
image = plt.imread(destImageUrl , format="JPG")
fig, ax = plt.subplots()
im = ax.imshow(image)
patch = patches.Circle((260, 200), radius=200, transform=ax.transData)
im.set_clip_path(patch)
ax.axis('off')
plt.show()
My .jpg file content:
Result: