How to add Azure Python SDK exceptions to try/except statements?
Question:
I’m new to Python. I have a working, monolithic Python program that I’m breaking into individual Python functions. I’d like to use the try:
– except:
pattern to catch specific exceptions for each function.
Example: Create a Key Vault client and retrieve a secret from Key Vault
import logging
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
credentials = DefaultAzureCredential()
def create_kv_client(kv_name, credentials):
kv_uri = 'https://' + kv_name + '.vault.azure.net'
kv_client = SecretClient(vault_url=kv_uri, credential=credentials)
return kv_client
kv_client = create_kv_client('mykeyvaultname', credentials)
def retrieve_secret(table_stg_acct_key, kv_client):
retrieved_account_key = kv_client.get_secret(table_stg_acct_key)
return retrieved_account_key
try:
retrieved_account_key = retrieve_secret('mykeyvaultsecretname', kv_client)
print(retrieved_account_key)
except:
logging.error('####### Failed to retrieve key from Key Vault #######')
raise BaseException
Rather than raise BaseException
here, I’d like to use the Azure Core exceptions module and log the actual message in the exception.
How is the except:
statement handled in the case where two exceptions could be raised?
Example: There could be two exceptions raised by the get_secret
method.
- If the Key Vault URL is incorrect, a
ServiceRequestError
is raised:
ServiceRequestError: <urllib3.connection.HTTPSConnection object at 0x000001BFA2299640>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed
- If the Key Vault secret name is incorrect, a ResourceNotFoundError is raised:
ResourceNotFoundError: (SecretNotFound) A secret with (name/id) notmykeyvaultsecretname was not found in this key vault. If you recently deleted this secret you may be able to recover it using the correct recovery command. For help resolving this issue, please see https://go.microsoft.com/fwlink/?linkid=2125182
How is this accomplished?
- Do I have to import the azure core exception module?
- An example of this pattern would be very helpful.
Answers:
The exception will be caught in order of "except" clauses, but beware of the subclass tree, since a except will catch all subclasses as well. For instance, this one leads to unreachable code.
try:
# do something
except BaseException:
# do something with
except DerivedException:
# assuming DerivedException is an extension of BaseException, you can't reach that code
So put them in most specific first.
In your Azure situation, this brings to something like:
from azure.core.exceptions import (
ClientAuthenticationError,
HttpResponseError,
ServiceRequestError,
ResourceNotFoundError,
AzureError
)
try:
# do KV stuff
except ClientAuthenticationError as e:
# Can occur if either tenant_id, client_id or client_secret is incorrect
logger.critical("Azure SDK was not able to connect to Key Vault", e)
except HttpResponseError as e:
# One reason is when Key Vault Name is incorrect
logger.critical("Possible wrong Vault name given", e)
except ServiceRequestError:
# Network error, I will let it raise to higher level
raise
except ResourceNotFoundError:
# Let's assume it's not big deal here, just let it go
pass
except AzureError as e:
# Will catch everything that is from Azure SDK, but not the two previous
logger.critical("Azure SDK was not able to deal with my query", e)
raise
except Exception as e:
# Anything else that is not Azure related (network, stdlib, etc.)
logger.critical("Unknown error I can't blame Azure for", e)
raise
I’m new to Python. I have a working, monolithic Python program that I’m breaking into individual Python functions. I’d like to use the try:
– except:
pattern to catch specific exceptions for each function.
Example: Create a Key Vault client and retrieve a secret from Key Vault
import logging
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
credentials = DefaultAzureCredential()
def create_kv_client(kv_name, credentials):
kv_uri = 'https://' + kv_name + '.vault.azure.net'
kv_client = SecretClient(vault_url=kv_uri, credential=credentials)
return kv_client
kv_client = create_kv_client('mykeyvaultname', credentials)
def retrieve_secret(table_stg_acct_key, kv_client):
retrieved_account_key = kv_client.get_secret(table_stg_acct_key)
return retrieved_account_key
try:
retrieved_account_key = retrieve_secret('mykeyvaultsecretname', kv_client)
print(retrieved_account_key)
except:
logging.error('####### Failed to retrieve key from Key Vault #######')
raise BaseException
Rather than raise BaseException
here, I’d like to use the Azure Core exceptions module and log the actual message in the exception.
How is the except:
statement handled in the case where two exceptions could be raised?
Example: There could be two exceptions raised by the get_secret
method.
- If the Key Vault URL is incorrect, a
ServiceRequestError
is raised:
ServiceRequestError: <urllib3.connection.HTTPSConnection object at 0x000001BFA2299640>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed
- If the Key Vault secret name is incorrect, a ResourceNotFoundError is raised:
ResourceNotFoundError: (SecretNotFound) A secret with (name/id) notmykeyvaultsecretname was not found in this key vault. If you recently deleted this secret you may be able to recover it using the correct recovery command. For help resolving this issue, please see https://go.microsoft.com/fwlink/?linkid=2125182
How is this accomplished?
- Do I have to import the azure core exception module?
- An example of this pattern would be very helpful.
The exception will be caught in order of "except" clauses, but beware of the subclass tree, since a except will catch all subclasses as well. For instance, this one leads to unreachable code.
try:
# do something
except BaseException:
# do something with
except DerivedException:
# assuming DerivedException is an extension of BaseException, you can't reach that code
So put them in most specific first.
In your Azure situation, this brings to something like:
from azure.core.exceptions import (
ClientAuthenticationError,
HttpResponseError,
ServiceRequestError,
ResourceNotFoundError,
AzureError
)
try:
# do KV stuff
except ClientAuthenticationError as e:
# Can occur if either tenant_id, client_id or client_secret is incorrect
logger.critical("Azure SDK was not able to connect to Key Vault", e)
except HttpResponseError as e:
# One reason is when Key Vault Name is incorrect
logger.critical("Possible wrong Vault name given", e)
except ServiceRequestError:
# Network error, I will let it raise to higher level
raise
except ResourceNotFoundError:
# Let's assume it's not big deal here, just let it go
pass
except AzureError as e:
# Will catch everything that is from Azure SDK, but not the two previous
logger.critical("Azure SDK was not able to deal with my query", e)
raise
except Exception as e:
# Anything else that is not Azure related (network, stdlib, etc.)
logger.critical("Unknown error I can't blame Azure for", e)
raise