Let's say I have the following code:
def do(i):
try:
1/i
except:
raise
finally:
raise NotImplementedError
It will try to divide 1 by a certain number, and will then in its finally clause, raise an Exception. What if I wanted to handle the exception in finally, but still want exceptions from try to be raised? (Note that I can't change how do works. I need to wrap dowithin my own exception handling logic).
To illustrate, let's try a few things:
do(1)
>>>
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
<ipython-input-16-bf2a92c9df1e> in <module>
----> 1 do(1)
<ipython-input-14-17793ae783da> in do(i)
5 raise
6 finally:
----> 7 raise NotImplementedError
NotImplementedError:
,
do(0)
>>>
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-14-17793ae783da> in do(i)
2 try:
----> 3 1/i
4 except:
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
NotImplementedError Traceback (most recent call last)
<ipython-input-17-dcdf66fecd31> in <module>
----> 1 do(0)
<ipython-input-14-17793ae783da> in do(i)
5 raise
6 finally:
----> 7 raise NotImplementedError
NotImplementedError:
,
try:
do(0)
except NotImplementedError:
print("passed")
except:
raise
>>>
passed
So, it is catching the NotImplementedError, which happens while handling the ZeroDivisionError and is therefore not raising ZeroDivisionError .
From the documentation, emphasis is mine:
If finally is present, it specifies a ‘cleanup’ handler. The try
clause is executed, including any except and else clauses. If an
exception occurs in any of the clauses and is not handled, the
exception is temporarily saved. The finally clause is executed. If
there is a saved exception it is re-raised at the end of the finally
clause. If the finally clause raises another exception, the saved
exception is set as the context of the new exception. If the finally
clause executes a return, break or continue statement, the saved
exception is discarded.
My addition to the emphasised part: otherwise the context is set to None.
In other words, the code that calls do(0) can't directly catch ZeroDevisionError since it is being masked by the NotImplementedError raised by the finally block. It will have to explicitly check the context of the NotImplemented exception.
try:
do(0)
except NotImplementedError as e:
print(e.__context__)
print(type(e.__context__))
Outputs
division by zero
<class 'ZeroDivisionError'>
To raise the full error stack only if the catched exception has a context, one could construct something like:
try:
do(0)
except NotImplementedError as e:
if e.__context__:
raise e
As the internal structure of the do() function is outside of your purview, then I would recommend pre-validation in the form of:
if number != 0:
do(number)
else:
raise ZeroDivisionError
It's hard to say for sure without more bits of the puzzle, but hope that helps.
Related
This question already has an answer here:
Disable exception chaining in python 3
(1 answer)
Closed 2 years ago.
I'm trying to run this:
try:
number = int(number)
except ValueError:
raise InvalidValueError("%s is not a valid base10 number." % number)
So, when I set number = '51651a'
I'm getting this:
Traceback (most recent call last):
File "test.py", line 16, in decbin
number = int(number)
ValueError: invalid literal for int() with base 10: '51651a'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 51, in <module>
print(decbin('51651a', True))
File "test.py", line 18, in decbin
raise InvalidValueError("%s is not a valid base10 number." % number)
__main__.InvalidValueError: 51651a is not a valid base10 number.
My question is that is there any way I don't see the line saying, "During handling of the above exception, another exception occurred:"
and all that's above it.
What you're looking for is disabling Exception Chaining with from None 1.
Change your raise statement to
raise InvalidValueError("%s is not a valid base10 number." % number) from None
and only your custom exception will be raised, without reference to the ValueError exception originally caught.
I am creating a program that lets you launch applications from Python. I had designed it so if a certain web browser was not downloaded, it would default to another one. Unfortunately, the try block seems to only function with one 'except FileNotFoundError.' Is there any way to have multiple of these in the same try block? Here's my (failing) code below:
app = input("\nWelcome to AppLauncher. You can launch your web browser by typing '1', your File Explorer by typing '2', or quit the program by typing '3': ")
if app == "1":
try:
os.startfile('chrome.exe')
except FileNotFoundError:
os.startfile('firefox.exe')
except FileNotFoundError:
os.startfile('msedge.exe')
If the user does not have Google Chrome downloaded, the program attempts to launch Mozilla Firefox. If that application is not found, it should open Microsoft Edge; instead it raises this error in IDLE (Please note that I have purposely misspelled chrome.exe and firefox.exe in order to simulate the programs essentially not existing):
Traceback (most recent call last):
File "C:/Users/NoName/AppData/Local/Programs/Python/Python38-32/applaunchermodule.py", line 7, in <module>
os.startfile('chome.exe')
FileNotFoundError: [WinError 2] The system cannot find the file specified: 'chome.exe'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:/Users/NoName/AppData/Local/Programs/Python/Python38-32/applaunchermodule.py", line 9, in <module>
os.startfile('frefox.exe')
FileNotFoundError: [WinError 2] The system cannot find the file specified: 'frefox.exe'
Is there any way to raise two of the same exceptions in a single try block?
for exe in ['chrome.exe','firefox.exe','msedge.exe']:
try:
os.startfile(exe)
break
except FileNotFoundError:
print(exe,"error")
For your exact case, I would suggest this:
priority_apps = ['chrome.exe', 'firefox.exe', 'msedge.exe'] # attempts to open in priority order
current_priority = 0
opened_app = False
while not opened_app and current_priority < len(priority_apps):
try:
os.startfile(priority_apps[current_priority])
opened_app = True
except Exception as e:
current_priority += 1
if not opened_app:
print("couldn't open anything! :(")
generic alternative with functions:
try:
do_something()
except Exception as e:
do_something_else1()
def do_something_else1():
try:
do_something()
except Exception as e:
do_something_else2()
generic alternative with nested try/except:
try:
do_something()
except Exception as e:
try:
do_something_else()
except Exception as e:
do_something_better()
I don't know why my 'start' pred won't work. I added some edits to pd.to_datetime but they didn't work.
This is my code:
pred = results.get_prediction(start=pd.to_datetime('2018-06-01'), dynamic=False)
pred_ci = pred.conf_int()
ax = y['2015':].plot(label='observed')
pred.predicted_mean.plot(ax=ax, label='One-step ahead Forecast', alpha=.7, figsize=(14, 4))
ax.fill_between(pred_ci.index,
pred_ci.iloc[:, 0],
pred_ci.iloc[:, 1], color='k', alpha=.2)
ax.set_xlabel('Date')
ax.set_ylabel('Retail_sold')
plt.legend()
plt.show()
and the log of my error always refers to my time format, I had to resample my data before, from daily data to monthly data before I started the analysis of the data and workaround the data, but I don't know why my data can't be read using pd.todatetime.
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
pandas/_libs/index.pyx in pandas._libs.index.DatetimeEngine.get_loc()
pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.Int64HashTable.get_item()
pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.Int64HashTable.get_item()
KeyError: 1546300800000000000
During handling of the above exception, another exception occurred:
KeyError Traceback (most recent call last)
/usr/local/lib/python3.6/dist-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
2896 try:
-> 2897 return self._engine.get_loc(key)
2898 except KeyError:
pandas/_libs/index.pyx in pandas._libs.index.DatetimeEngine.get_loc()
pandas/_libs/index.pyx in pandas._libs.index.DatetimeEngine.get_loc()
KeyError: Timestamp('2019-01-01 00:00:00')
During handling of the above exception, another exception occurred:
KeyError Traceback (most recent call last)
pandas/_libs/index.pyx in pandas._libs.index.DatetimeEngine.get_loc()
pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.Int64HashTable.get_item()
pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.Int64HashTable.get_item()
KeyError: 1546300800000000000
During handling of the above exception, another exception occurred:
KeyError Traceback (most recent call last)
11 frames
pandas/_libs/index.pyx in pandas._libs.index.DatetimeEngine.get_loc()
pandas/_libs/index.pyx in pandas._libs.index.DatetimeEngine.get_loc()
KeyError: Timestamp('2019-01-01 00:00:00')
During handling of the above exception, another exception occurred:
KeyError Traceback (most recent call last)
pandas/_libs/index.pyx in pandas._libs.index.DatetimeEngine.get_loc()
pandas/_libs/index.pyx in pandas._libs.index.DatetimeEngine.get_loc()
KeyError: Timestamp('2019-01-01 00:00:00')
During handling of the above exception, another exception occurred:
KeyError Traceback (most recent call last)
/usr/local/lib/python3.6/dist-packages/statsmodels/tsa/base/tsa_model.py in _get_prediction_index(self, start, end, index, silent)
522 start, start_index, start_oos = self._get_index_label_loc(start)
523 except KeyError:
--> 524 raise KeyError('The `start` argument could not be matched to a'
525 ' location related to the index of the data.')
526 if end is None:
KeyError: 'The `start` argument could not be matched to a location related to the index of the data.'
I used Google Colab and Python 3.7.
Does anyone have the solution of my problem?
The underlying problem here is that your data doesn't have an index with an associated frequency, because your data skips days (for example going from 2016/2/5 to 2016/2/14).
In a similar issue my problem was that I was passing as value data a list and I needed to convert in a pd serie
data_to predict = pd.Series(imput_data, index=myIndex)
You should set the dataset's index with time columns like this:
df["Time"] = pd.to_datetime(df['Time'], infer_datetime_format=True)
df = df.set_index(["Time"])
you can try the following:
predictions = results.predict(start=train_data.shape[0],end=(train_data.shape[0]+test_data.shape[0]-1), dynamic=False)
I am trying to figure out, how to get the actual file/module name in exception message in Databricks.
import traceback
def bad():
print("hello")
a = 1/0
def main():
try:
bad()
except Exception as e:
print(traceback.format_exc())
main()
When I run this the exception message I get like -
hello
Traceback (most recent call last):
File "<command-162594828857243>", line 8, in main
bad()
File "<command-162594828857243>", line 4, in bad
a = 1/0
ZeroDivisionError: division by zero
The "<command-162594828857243>" doesn't help at the time of debugging. I want the actual file/module name there.
I am creating a process to execute a function. If the function raises an exception I am not able to catch it. The following is a sample code.
from multiprocessing import Process
import traceback
import time
class CustomTimeoutException(Exception):
pass
def temp1():
time.sleep(5)
print('In temp1')
raise Exception('I have raised an exception')
def main():
try:
p = Process(target=temp1)
p.start()
p.join(10)
if p.is_alive():
p.terminate()
raise CustomTimeoutException('Timeout')
except CustomTimeoutException as e:
print('in Custom')
print(e)
except Exception as e:
print('In exception')
print(e)
if __name__ == "__main__":
main()
When I run the above code the exception raised within temp1 does not get caught. Below is the sample output
In temp1
Process Process-1:
Traceback (most recent call last):
File "/usr/lib/python3.5/multiprocessing/process.py", line 249, in _bootstrap
self.run()
File "/usr/lib/python3.5/multiprocessing/process.py", line 93, in run
self._target(*self._args, **self._kwargs)
File "temp.py", line 12, in temp1
raise Exception('I have raised an exception')
Exception: I have raised an exception
I have also tried overwriting the run method of the Process class as mentioned in https://stackoverflow.com/a/33599967/9971556 Wasn't very helpful.
Expected output:
In exception
I have raised an exception