I was going to use send_mail function to send email, and I was hoping that using fail_silently=True would prevent this function from raising exceptions.
It turns out it does work if SMTPException is raised; however I noticed it doesn't intercept socket.error exception - so if STMP server is down, an exception will be raised even with fail_silently=True
I'm now wondering how to get the complete list of exceptions raised by send_mail so I can catch them in try/except loop. Any suggestions?
I'd say that catch an Exception is a very final approach. Since both SMTPException and socket.error are children of IOError you can catch an IOError instead. If you'll ever catch something else - you can add this to your catch list later.
Related
I am trying to integrate stripe with my django project, so I try to create a PaymentIntent and if a network communication with stripe failed I will try to do like this:
try:
intent = stripe.PaymentIntent.create(
amount=100,
currency='usd'
)
return JsonResponse({
'clientSecret': intent['client_secret']
})
except stripe.error.CardError as e:
pass
except stripe.error.RateLimitError as e:
pass
except stripe.error.InvalidRequestError as e:
pass
except stripe.error.AuthenticationError as e:
pass
except stripe.error.APIConnectionError as e:
try:
intent_cancel = stripe.PaymentIntent.cancel(
intent['id']
)
except Exception as e:
# (If an exception is raised this means that the PaymentIntent was not created, I am right ?)
# I redirect the user to the payment page and inform him
# that a network problem has occurred and ask him to repeat his request
pass
except stripe.error.StripeError as e:
pass
except Exception as e:
pass
My questions are:
1 Is my way of handling the exception right ?
2 Can I apply this logic to the other exception ?
3 In the documentation they say that we should use an idempotency_key to retry the failed requests, how can I implement this ? and what about if I retry the failed request and it fails again, what should I do ?
You have 2 Stripe API requests in the same try block. This means if one succeeds but the other fails due to a connection error you'll treat both as failed. A better flow would be to only have one API operation per try/catch block.
You also have a request to cancel a hardcoded PaymentIntent after your code returns a JSON object. Since the return isn't conditional this is likely dead code.
The cancel logic in the case of a connection error doesn't make sense here. You should only hit this path if the connection failed and the intent wasn't created, so trying to cancel the non-existent PaymentIntent will likely result in yet another error. Instead you should introduce retry logic here. Luckily stripe-python has this built in specifically for network errors: https://github.com/stripe/stripe-python#configuring-automatic-retries
Once all retries have failed, you should probably log that somewhere and inform your user that a problem occurred and that they should try again later.
As for idempotency keys, the Stripe docs have a primer on that here: https://stripe.com/docs/api/idempotent_requests?lang=python
I am trying to execute some statements within Try block. I am calling an API and performing some operations. There is one specific operation which is resulting in RuntimeError which is puked while running the program, although I am catching it with an exception. How do I go about avoiding the errors being puked from Try block?
try:
call API and perform some tasks.
encounters an error here
Except RunTimeError as ex:
print(ex)
Well as Susmit R. Veena said the point of try and except is to catch the error thrown in the try block.
In case you have some flow you want to ignore from its exceptions in the try block, than you can have a nested try catch block for the specific error you want to ignore and keep doing the logic after it is ignored.
for example:
try:
try:
call API and perform some tasks.
encounters an error here
Except TheErrorYouWantToIngore:
pass
keep on doing some stuff even TheErrorYouWantToIngore has been throwed
Except RunTimeError as ex:
print(ex)
the whole point of try and except is to catch the errors thrown by the code in try block in except block. Post the code for solution to the error
I'm trying to add SSE functionality to my server application using Redis PubSub, guided by many articles i.e:
how-to-use-actioncontollerlive-along-with-resque-redis.
The server is hosted in Heroku, thus heartbeating is necessary as well.
...
sse = SSE.new(response.stream)
begin
redis = Redis.new(:url => ENV['REDISCLOUD_URL'])
redis.subscribe(<UUID>, HEARTBEAT_CHANNEL) do |on|
on.message do |channel, data|
begin
if channel == HEARTBEAT_CHANNEL
sse.write('', event: "hb")
else
sse.write(data, event: "offer_update")
end
rescue StandardError => e #I'll call this section- "internal rescue"
puts "Internal: #{$!}"
redis.quit
sse.close
puts "SSE was closed
end
end
end
rescue StandardError => e #I'll call this section- "external rescue"
puts "External: #{$!}"
ensure
redis.quit
sse.close
puts "sse was closed"
end
The questions:
I didn't see the "Internal rescue" in any place over the net talking about SSE. but I don't get who can catch an exception if raised by the sse.write? The common scenario is that HB is sent while client isn't connected anymore which makes this section so critical ("Internal: client disconnected" is appeared). Am I right?
In which case will the "external rescue" be triggered? Does a client disconnection cause sse.write to raise an exception in the "inner block" (inside the on.message body)? because it was never caught by the external rescue when I tried to simulate it tens of times.
This code suffers as well. redis.quit in the internal rescue section raises another exception which is caught by the external rescue statement: External: undefined method 'disconnect' for #<Redis::SubscribedClient:0x007fa8cd54b820>. So - how should it done? how can I recognize ASAP a client disconnection in order to free the memory&socket?
How can it be that exceptions raised by the sse.write have NOT been caught by the external rescue (as it should be from beginning) while another error (described in my 3rd question) has been caught? all of this code (outer+inner sections) is running in the same thread, right? I'd be happy for a deep explaination.
You catch the exception inside the subscribe, and so redis doesn't know about it and will not stop it's inner loop properly. redis.quit will cause it to crash and stop since it cannot keep waiting for a message. This is obviously not a good way to do it.
If your code throws an exception inside the subscribe it will cause redis to gracefully unsubscribe and your exception can be rescued outside, as in your "external rescue".
Another point is that you shouldn't catch exceptions without fully handling them, and you should never catch generic exceptions without re-raising them. In this case you can safely let the ClientDisconnected exception bubble to Rails' code.
Here's how your controller's code should look like:
def subscribe
sse = SSE.new(response.stream)
redis = Redis.new(:url => ENV['REDISCLOUD_URL'])
redis.subscribe(<UUID>, HEARTBEAT_CHANNEL) do |on|
on.message do |channel, data|
if channel == HEARTBEAT_CHANNEL
sse.write('', event: "hb")
else
sse.write(data, event: "offer_update")
end
end
end
ensure
redis.quit if reddis # might not have had a chance to initialize yet
sse.close if sse # might not have had a chance to initialize yet
puts "sse was closed"
end
Somehow, using django 1.7 with the default email backend, I get an error: 111 Connection Refused. This is triggered as an exception, even when the fail_silently parameter is True.
The line goes like this:
return send_mail(subject=u"Bienvenido a Mi CNT!",
message=render_to_string('micnt/mail.welcome.txt', context),
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=[email_address],
fail_silently=True,
html_message=render_to_string('micnt/mail.welcome.html', context))
I know how to fix the excepcion (I forgot to configure certain parameters). However, there will be cases where, perhaps, the exception will be due to other reasons (e.g. I correctly specified the mail parameters, but the server got down).
Why is fail_silently not working? What is the "scope" of fail_silently? (i.e. which errors does it cover, and which errors does it let pass to the invoker?).
I would like to correctly cover the exceptions without having to:
try:
return send_mail(...)
except Exception as e:
# I want to understand what exception types will be triggered here.
pass
fail_silently will only catch SMTPException's when send_mail attempts to connect to email server (executes get_connection).
I like to take issues like this as an opportunity to look into the django source code, which contains all the answers:
https://github.com/django/django/blob/master/django/core/mail/backends/smtp.py#L69
I had been trying hard to figure out why the exceptions thrown from StartElement event handler are not being caught by my application which makes use of expat parser( in C). The application just terminates saying that it cannot find catch blocks, though I have all the catch blocks in place. It is just that since exceptions are being thrown from my own event handlers, XML_Parse API of expat is unable to pass it on to my code where I have all the catch blocks. One of the stackoverflow user with name 'Michael Anderson" suggested to rebuild expat lib with necessary gcc flags to make expat lib handle exceptions. Can someone let me know what flags are those? Or Suggest a better way out to handle errors in event handlers like startelement, endelement etc.
I somehow want XML_Parse API to return 0 if I encounter any exception in my registered event handlers. Please help. Thanks in advance.
Here is the code:
try
{
if( ! XML_Parse(.....) )
{
throw exception;
}
}
catch(...)
{
}
In the working scenario, if XML_Parse encounters a malformed xml file, it promptly returns zero, and I get into if block and throw exception, and it is caught fine.
But in the problematic case, the exceptions are being thrown from the event handlers but my application dumps core, and core stack says that it cannot find catch and finally calling std::terminate and abort.
Now, how do I make XML_Parse to return zero when I want to throw user defined exception from event handlers?
As per expat.h, you should invoke XML_StopParser(parser, 0) when you encounter an error in your handler that warrants aborting the parse.
XML_Parse will then return XML_FALSE. At that point you can invoke your application-specific error handling