|
import nbformat |
|
from nbconvert.preprocessors import ExecutePreprocessor |
|
from nbconvert.preprocessors.execute import CellExecutionError |
|
import base64 |
|
from io import BytesIO |
|
import re |
|
|
|
def get_error_message(traceback_str): |
|
lines = traceback_str.split('\n') |
|
for line in lines: |
|
if 'Error:' in line: |
|
return line |
|
return None |
|
|
|
|
|
nb = nbformat.v4.new_notebook() |
|
|
|
SITE_PKG_ERROR_PREFIX = 'File /usr/local/lib/python3.8/' |
|
|
|
code_sample = """ |
|
import yfinance as yf |
|
import matplotlib.pyplot as plt |
|
|
|
# Get the data of the Tesla USD stock price |
|
tsla = yf.Ticker("TSLA-USD") |
|
|
|
# Get the historical prices for the last 3 months |
|
tsla_hist = tsla.history(period="max", start="3 months ago") |
|
|
|
# Plot the close prices |
|
tsla_hist['Close'].plot(figsize=(16, 9)) |
|
plt.title('Tesla stock price last 3 months') |
|
plt.xlabel('Date') |
|
plt.ylabel('Price (USD)') |
|
plt.show() |
|
""" |
|
|
|
|
|
code_cell = nbformat.v4.new_code_cell(source=code_sample) |
|
nb.cells.append(code_cell) |
|
|
|
|
|
ep = ExecutePreprocessor(timeout=600, kernel_name='python3') |
|
output_str, error_str = None, None |
|
|
|
try: |
|
ep.preprocess(nb) |
|
if nb.cells[0].outputs: |
|
for i,c in enumerate(nb.cells[-1].outputs): |
|
print(f'[{i+1}] : {c}') |
|
|
|
except CellExecutionError as e: |
|
error_str = e |
|
|
|
if error_str is not None: |
|
|
|
filtered_error_msg = error_str.__str__().split('An error occurred while executing the following cell')[-1].split("\n------------------\n")[-1] |
|
raw_error_msg = "".join(filtered_error_msg) |
|
|
|
|
|
|
|
ansi_escape = re.compile(r'\x1b\[[0-?]*[ -/]*[@-~]') |
|
error_msg = ansi_escape.sub('', raw_error_msg) |
|
|
|
error_msg_only_cell = error_msg.split(SITE_PKG_ERROR_PREFIX) |
|
for i,c in enumerate(error_msg_only_cell): |
|
if i ==0: |
|
print(f'[{i+1}]\n{c.strip()}\n---') |
|
if i==3: |
|
error_header = get_error_message(c) |
|
print(error_header) |
|
|
|
|
|
|
|
error_lines = error_msg.split("\n") |
|
|
|
|
|
error_lines = error_lines[:next(i for i, line in enumerate(error_lines) if 'Error:' in line) + 1] |
|
|
|
|
|
error_msg = "\n".join(error_lines) |