- Newest
- Most votes
- Most comments
Starting with >> Troubleshooting Steps for Flask Application Issues on Amazon Lightsail
Check Logs: Inspect server logs on your Amazon Lightsail instance for errors or warnings.
Environment Differences: Ensure that the environments on Amazon Lightsail and your local machine are identical, including Python, Flask, and other dependencies.
CORS Issues: Verify that Cross-Origin Resource Sharing (CORS) is correctly configured if your application interacts with external APIs.
Form Handling: Check the form handling logic in your Flask routes to ensure all required form fields are properly validated and processed.
JavaScript Errors: Use the browser's developer console to check for JavaScript errors that might be affecting the dropdowns or form functionality.
Network Requests: Inspect network requests in the browser's developer console to ensure they are functioning correctly and receiving expected responses.
Recap with steps: Check Logs Compare Environments Verify CORS Configuration Inspect Form Handling Check JavaScript Console Inspect Network Requests Verify Docker Configuration Check Permissions and Firewall Settings Run Flask Application Directly on Lightsail Providing code snippets, Dockerfile, and error logs can help with more targeted troubleshooting.
answered 2 years ago
Hello.
Troubleshooting is difficult with only error messages on the browser.
How about trying logging to get the application log?
https://flask.palletsprojects.com/en/2.3.x/logging/
Thanks! Updated the post with Amazon CLI error log screenshot.
Is it possible for you to share not only the error message but also the relevant code?
Thank you for sharing the code.
Judging from the error message and code, I think it occurred when trying to perform a direct multidimensional index operation on a Pandas DataFrame or Series.
I think the following stackoverflow answers will be helpful.
https://stackoverflow.com/questions/75939123/valueerror-multi-dimensional-indexing-e-g-obj-none-is-no-longer-suppor
I think the problem is in the following part of your code.
def compare_stocks(symbol1, symbol2):
df1 = fetch_historical_data(symbol1)
df2 = fetch_historical_data(symbol2)
if df1 is None or df2 is None:
return None, None, None, None, None, None, f"Could not fetch data for one or both symbols."
common_start_date = max(df1.index.min(), df2.index.min())
df1 = df1[df1.index >= common_start_date]
df2 = df2[df2.index >= common_start_date]
if df1.empty or df2.empty:
return None, None, None, None, None, None, "No overlapping data available for the selected stocks."
else:
growth1, yearly_returns1 = calculate_growth(df1.copy())
growth2, yearly_returns2 = calculate_growth(df2.copy())
cumulative_returns1 = [0]
cumulative_returns2 = [0]
for val1, val2 in zip(growth1.values[1:], growth2.values[1:]):
cumulative_returns1.append(((val1 - growth1.values[0]) / 100) * 100)
cumulative_returns2.append(((val2 - growth2.values[0]) / 100) * 100)
return growth1, growth2, yearly_returns1, yearly_returns2, cumulative_returns1, cumulative_returns2, None
So, why not try returning a numpy array with "to_numpy()" as shown below?
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_numpy.html#pandas.DataFrame.to_numpy
def compare_stocks(symbol1, symbol2):
df1 = fetch_historical_data(symbol1)
df2 = fetch_historical_data(symbol2)
if df1 is None or df2 is None:
return None, None, None, None, None, None, f"Could not fetch data for one or both symbols."
common_start_date = max(df1.index.min(), df2.index.min())
df1 = df1[df1.index >= common_start_date]
df2 = df2[df2.index >= common_start_date]
if df1.empty or df2.empty:
return None, None, None, None, None, None, "No overlapping data available for the selected stocks."
else:
growth1, yearly_returns1 = calculate_growth(df1.copy())
growth2, yearly_returns2 = calculate_growth(df2.copy())
cumulative_returns1 = [0]
cumulative_returns2 = [0]
growth1_values = growth1.to_numpy() # <-- add
growth2_values = growth2.to_numpy() # <-- add
for val1, val2 in zip(growth1_values[1:], growth2_values[1:]):
cumulative_returns1.append(((val1 - rowth1_values[0]) / 100) * 100) # <-- edit
cumulative_returns2.append(((val2 - growth2_values[0]) / 100) * 100) # <-- edit
return growth1, growth2, yearly_returns1, yearly_returns2, cumulative_returns1, cumulative_returns2, None
These are the original codes on VS Code from where I started with launching Ubuntu instance, trying to make live the same project through Amazon Lightsail:
- App.py
from flask import Flask, render_template, request
import requests
import pandas as pd
import matplotlib.pyplot as plt
from io import BytesIO, StringIO
import base64
import csv
import datetime
app = Flask(__name__)
# Replace with your actual API key from Alpha Vantage
API_KEY = "FI5B9EM5VOZTW6WJ"
def fetch_stock_symbols(exchange):
url = f"https://www.alphavantage.co/query?function=LISTING_STATUS&apikey={API_KEY}&exchange={exchange}"
try:
response = requests.get(url)
response.raise_for_status()
if response.headers['Content-Type'] == 'application/x-download':
csv_data = StringIO(response.text)
csv_reader = csv.DictReader(csv_data)
return [row['symbol'] for row in csv_reader if not row['symbol'].isdigit()]
else:
print("Unexpected response content type:", response.headers['Content-Type'])
return []
except requests.RequestException as e:
print(f"Error fetching symbols: {e}")
return []
def fetch_historical_data(symbol):
ten_years_ago = datetime.datetime.now() - datetime.timedelta(days=10*365)
start_date = ten_years_ago.strftime('%Y-%m-%d')
url = f"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={symbol}&outputsize=full&apikey={API_KEY}"
try:
response = requests.get(url)
response.raise_for_status()
data = response.json()
if "Time Series (Daily)" in data:
df = pd.DataFrame.from_dict(data["Time Series (Daily)"], orient="index")
df = df.rename(columns={"4. close": "close"})
df["close"] = pd.to_numeric(df["close"])
df.index = pd.to_datetime(df.index)
df = df[df.index >= start_date]
df.sort_index(inplace=True)
return df
return None
except requests.RequestException as e:
print(f"Error fetching data for {symbol}: {e}")
return None
def calculate_growth(df, start_value=100):
df = df.resample("Y").last()
growth = (df["close"] / df["close"].iloc[0]) * start_value
yearly_returns = (growth.pct_change() * 100).round(2)
return growth, yearly_returns
def compare_stocks(symbol1, symbol2):
df1 = fetch_historical_data(symbol1)
df2 = fetch_historical_data(symbol2)
if df1 is None or df2 is None:
return None, None, None, None, None, None, f"Could not fetch data for one or both symbols."
common_start_date = max(df1.index.min(), df2.index.min())
df1 = df1[df1.index >= common_start_date]
df2 = df2[df2.index >= common_start_date]
if df1.empty or df2.empty:
return None, None, None, None, None, None, "No overlapping data available for the selected stocks."
else:
growth1, yearly_returns1 = calculate_growth(df1.copy())
growth2, yearly_returns2 = calculate_growth(df2.copy())
cumulative_returns1 = [0]
cumulative_returns2 = [0]
for val1, val2 in zip(growth1.values[1:], growth2.values[1:]):
cumulative_returns1.append(((val1 - growth1.values[0]) / 100) * 100)
cumulative_returns2.append(((val2 - growth2.values[0]) / 100) * 100)
return growth1, growth2, yearly_returns1, yearly_returns2, cumulative_returns1, cumulative_returns2, None
@app.route("/", methods=["GET", "POST"])
def index():
symbols = []
if request.method == "POST":
exchange = request.form["exchange"]
symbol1 = request.form["symbol1"]
symbol2 = request.form["symbol2"]
symbols = fetch_stock_symbols(exchange)
growth1, growth2, yearly_returns1, yearly_returns2, cumulative_returns1, cumulative_returns2, error_message = compare_stocks(symbol1, symbol2)
if error_message:
return render_template("index.html", symbols=symbols, error_message=error_message)
plt.figure(figsize=(10, 6))
plt.plot(growth1.index, growth1.values, label=symbol1)
plt.plot(growth2.index, growth2.values, label=symbol2)
plt.xlabel("Year")
plt.ylabel("Value of $100 Investment")
plt.title("Stock Comparison")
plt.legend()
img = BytesIO()
plt.savefig(img, format='png')
img.seek(0)
img_base64 = base64.b64encode(img.getvalue()).decode('utf-8')
start_date = growth1.index[0].strftime('%Y-%m-%d')
end_date = growth1.index[-1].strftime('%Y-%m-%d')
final_value1 = growth1.values[-1]
final_value2 = growth2.values[-1]
comparison_message = (
f"On {start_date}, $100 invested in {symbol1} would be worth ${final_value1:.2f} on {end_date}.\n"
f"On {start_date}, $100 invested in {symbol2} would be worth ${final_value2:.2f} on {end_date}."
)
table_data = []
for year, val1, ret1, val2, ret2, cum_ret1, cum_ret2 in zip(
growth1.index.year,
growth1.values,
yearly_returns1.values,
growth2.values,
yearly_returns2.values,
cumulative_returns1,
cumulative_returns2
):
table_data.append({
"year": year,
"val1": val1,
"ret1": ret1,
"val2": val2,
"ret2": ret2,
"cum_ret1": cum_ret1,
"cum_ret2": cum_ret2
})
return render_template(
"result.html",
img_data=img_base64,
comparison_message=comparison_message,
table_data=table_data,
start_date=start_date,
end_date=end_date,
symbol1=symbol1,
symbol2=symbol2,
)
else:
# Default to NASDAQ symbols on initial load
symbols = fetch_stock_symbols('NASDAQ')
return render_template("index.html", symbols=symbols)
if __name__ == "__main__":
app.run(debug=True)
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Stock Comparison</title>
</head>
<body>
<h1>Compare Stocks</h1>
<form method="POST">
<label for="exchange">Select Stock Exchange:</label>
<select name="exchange" id="exchange" onchange="this.form.submit()">
<option value="NASDAQ" {% if request.form.get('exchange') == 'NASDAQ' %}selected{% endif %}>NASDAQ</option>
<option value="NYSE" {% if request.form.get('exchange') == 'NYSE' %}selected{% endif %}>NYSE</option>
<option value="AMEX" {% if request.form.get('exchange') == 'AMEX' %}selected{% endif %}>AMEX</option>
</select>
<br><br>
<label for="symbol1">Stock Symbol 1:</label>
<select name="symbol1" id="symbol1" required>
{% for symbol in symbols %}
<option value="{{ symbol }}">{{ symbol }}</option>
{% endfor %}
</select>
<br><br>
<label for="symbol2">Stock Symbol 2:</label>
<select name="symbol2" id="symbol2" required>
{% for symbol in symbols %}
<option value="{{ symbol }}">{{ symbol }}</option>
{% endfor %}
</select>
<br><br>
<button type="submit">Compare</button>
</form>
{% if error_message %}
<p style="color: red;">{{ error_message }}</p>
{% endif %}
</body>
</html>
- result.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Stock Comparison Result</title>
</head>
<body>
<h1>Stock Comparison Result</h1>
<p>{{ comparison_message }}</p>
<img src="data:image/png;base64,{{ img_data }}" alt="Stock Comparison Graph">
<table border="1">
<thead>
<tr>
<th>Year</th>
<th>{{ symbol1 }} Value</th>
<th>{{ symbol1 }} Yearly Return (%)</th>
<th>{{ symbol2 }} Value</th>
<th>{{ symbol2 }} Yearly Return (%)</th>
<th>{{ symbol1 }} Cumulative Return (%)</th>
<th>{{ symbol2 }} Cumulative Return (%)</th>
</tr>
</thead>
<tbody>
{% for row in table_data %}
<tr>
<td>{{ row.year }}</td>
<td>{{ row.val1 }}</td>
<td>{{ row.ret1 }}</td>
<td>{{ row.val2 }}</td>
<td>{{ row.ret2 }}</td>
<td>{{ row.cum_ret1 }}</td>
<td>{{ row.cum_ret2 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<br>
<a href="/">Back to Comparison</a>
</body>
</html>
answered 2 years ago
While troubleshooting in order to make live for Ubuntu, here are the 2 versions of app.py (with errors):
- app.py
from flask import Flask, render_template, request
import requests
import pandas as pd
import matplotlib.pyplot as plt
from io import BytesIO, StringIO
import base64
import csv
import datetime
app = Flask(__name__)
# Replace with your actual API key from Alpha Vantage
API_KEY = "FI5B9EM5VOZTW6WJ"
def fetch_stock_symbols(exchange):
url = f"https://www.alphavantage.co/query?function=LISTING_STATUS&apikey={API_KEY}&exchange={exchange}"
try:
response = requests.get(url)
response.raise_for_status()
if response.headers['Content-Type'] == 'application/x-download':
csv_data = StringIO(response.text)
csv_reader = csv.DictReader(csv_data)
return [row['symbol'] for row in csv_reader if not row['symbol'].isdigit()]
else:
print("Unexpected response content type:", response.headers['Content-Type'])
return []
except requests.RequestException as e:
print(f"Error fetching symbols: {e}")
return []
def fetch_historical_data(symbol):
ten_years_ago = datetime.datetime.now() - datetime.timedelta(days=10*365)
start_date = ten_years_ago.strftime('%Y-%m-%d')
url = f"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={symbol}&outputsize=full&apikey={API_KEY}"
try:
response = requests.get(url)
response.raise_for_status()
data = response.json()
if "Time Series (Daily)" in data:
df = pd.DataFrame.from_dict(data["Time Series (Daily)"], orient="index")
df = df.rename(columns={"4. close": "close"})
df["close"] = pd.to_numeric(df["close"])
df.index = pd.to_datetime(df.index)
df = df[df.index >= start_date]
df.sort_index(inplace=True)
return df
return None
except requests.RequestException as e:
print(f"Error fetching data for {symbol}: {e}")
return None
def calculate_growth(df, start_value=100):
df = df.resample("Y").last()
growth = (df["close"] / df["close"].iloc[0]) * start_value
yearly_returns = (growth.pct_change() * 100).round(2)
return growth, yearly_returns
def compare_stocks(symbol1, symbol2):
df1 = fetch_historical_data(symbol1)
df2 = fetch_historical_data(symbol2)
if df1 is None or df2 is None:
return None, None, None, None, None, None, f"Could not fetch data for one or both symbols."
common_start_date = max(df1.index.min(), df2.index.min())
df1 = df1[df1.index >= common_start_date]
df2 = df2[df2.index >= common_start_date]
if df1.empty or df2.empty:
return None, None, None, None, None, None, "No overlapping data available for the selected stocks."
else:
growth1, yearly_returns1 = calculate_growth(df1.copy())
growth2, yearly_returns2 = calculate_growth(df2.copy())
cumulative_returns1 = [0]
cumulative_returns2 = [0]
for val1, val2 in zip(growth1.values[1:], growth2.values[1:]):
cumulative_returns1.append(((val1 - growth1.values[0]) / 100) * 100)
cumulative_returns2.append(((val2 - growth2.values[0]) / 100) * 100)
return growth1, growth2, yearly_returns1, yearly_returns2, cumulative_returns1, cumulative_returns2, None
@app.route("/", methods=["GET", "POST"])
def index():
symbols = []
if request.method == "POST":
exchange = request.form["exchange"]
symbol1 = request.form["symbol1"]
symbol2 = request.form["symbol2"]
symbols = fetch_stock_symbols(exchange)
growth1, growth2, yearly_returns1, yearly_returns2, cumulative_returns1, cumulative_returns2, error_message = compare_stocks(symbol1, symbol2)
if error_message:
return render_template("index.html", symbols=symbols, error_message=error_message)
plt.figure(figsize=(10, 6))
plt.plot(growth1.index, growth1.values, label=symbol1)
plt.plot(growth2.index, growth2.values, label=symbol2)
plt.xlabel("Year")
plt.ylabel("Value of $100 Investment")
plt.title("Stock Comparison")
plt.legend()
img = BytesIO()
plt.savefig(img, format='png')
img.seek(0)
img_base64 = base64.b64encode(img.getvalue()).decode('utf-8')
start_date = growth1.index[0].strftime('%Y-%m-%d')
end_date = growth1.index[-1].strftime('%Y-%m-%d')
final_value1 = growth1.values[-1]
final_value2 = growth2.values[-1]
comparison_message = (
f"On {start_date}, $100 invested in {symbol1} would be worth ${final_value1:.2f} on {end_date}.\n"
f"On {start_date}, $100 invested in {symbol2} would be worth ${final_value2:.2f} on {end_date}."
)
table_data = []
for year, val1, ret1, val2, ret2, cum_ret1, cum_ret2 in zip(
growth1.index.year,
growth1.values,
yearly_returns1.values,
growth2.values,
yearly_returns2.values,
cumulative_returns1,
cumulative_returns2
):
table_data.append({
"year": year,
"val1": val1,
"ret1": ret1,
"val2": val2,
"ret2": ret2,
"cum_ret1": cum_ret1,
"cum_ret2": cum_ret2
})
return render_template(
"result.html",
img_data=img_base64,
comparison_message=comparison_message,
table_data=table_data,
start_date=start_date,
end_date=end_date,
symbol1=symbol1,
symbol2=symbol2,
)
else:
# Default to NASDAQ symbols on initial load
symbols = fetch_stock_symbols('NASDAQ')
return render_template("index.html", symbols=symbols)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
answered 2 years ago
- app.py
from flask import Flask, render_template, request
import requests
import pandas as pd
import matplotlib.pyplot as plt
from io import BytesIO, StringIO
import base64
import csv
import datetime
import numpy as np
app = Flask(__name__)
API_KEY = "FI5B9EM5VOZTW6WJ"
def fetch_stock_symbols(exchange):
url = f"https://www.alphavantage.co/query?function=LISTING_STATUS&apikey={API_KEY}&exchange={exchange}"
try:
response = requests.get(url)
response.raise_for_status()
if response.headers['Content-Type'] == 'application/x-download':
csv_data = StringIO(response.text)
csv_reader = csv.DictReader(csv_data)
return [row['symbol'] for row in csv_reader if not row['symbol'].isdigit()]
else:
print("Unexpected response content type:", response.headers['Content-Type'])
return []
except requests.RequestException as e:
print(f"Error fetching symbols: {e}")
return []
def fetch_historical_data(symbol):
ten_years_ago = datetime.datetime.now() - datetime.timedelta(days=10*365)
start_date = ten_years_ago.strftime('%Y-%m-%d')
url = f"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={symbol}&outputsize=full&apikey={API_KEY}"
try:
response = requests.get(url)
response.raise_for_status()
data = response.json()
if "Time Series (Daily)" in data:
df = pd.DataFrame.from_dict(data["Time Series (Daily)"], orient="index")
df = df.rename(columns={"4. close": "close"})
df["close"] = pd.to_numeric(df["close"])
df.index = pd.to_datetime(df.index)
df = df[df.index >= start_date]
df.sort_index(inplace=True)
return df
return None
except requests.RequestException as e:
print(f"Error fetching data for {symbol}: {e}")
return None
def calculate_growth(df, start_value=100):
df = df.resample("Y").last()
growth = (df["close"] / df["close"].iloc[0]) * start_value
yearly_returns = (growth.pct_change() * 100).round(2)
return growth, yearly_returns
def compare_stocks(symbol1, symbol2):
df1 = fetch_historical_data(symbol1)
df2 = fetch_historical_data(symbol2)
if df1 is None or df2 is None:
return None, None, None, None, None, None, f"Could not fetch data for one or both symbols."
common_start_date = max(df1.index.min(), df2.index.min())
df1 = df1[df1.index >= common_start_date]
df2 = df2[df2.index >= common_start_date]
if df1.empty or df2.empty:
return None, None, None, None, None, None, "No overlapping data available for the selected stocks."
else:
growth1, yearly_returns1 = calculate_growth(df1.copy())
growth2, yearly_returns2 = calculate_growth(df2.copy())
cumulative_returns1 = [0]
cumulative_returns2 = [0]
for val1, val2 in zip(growth1.values[1:], growth2.values[1:]):
cumulative_returns1.append(((val1 - growth1.values[0]) / 100) * 100)
cumulative_returns2.append(((val2 - growth2.values[0]) / 100) * 100)
return growth1, growth2, yearly_returns1, yearly_returns2, cumulative_returns1, cumulative_returns2, None
@app.before_request
def validate_request():
if request.method == "POST":
print("Form data received:", request.form)
if not request.form.get("exchange") or not request.form.get("symbol1") or not request.form.get("symbol2"):
return {"error": "Missing form data"}, 400
@app.route("/", methods=["GET", "POST"])
def index():
symbols = []
if request.method == "POST":
exchange = request.form["exchange"]
symbol1 = request.form["symbol1"]
symbol2 = request.form["symbol2"]
symbols = fetch_stock_symbols(exchange)
growth1, growth2, yearly_returns1, yearly_returns2, cumulative_returns1, cumulative_returns2, error_message = compare_stocks(symbol1, symbol2)
if error_message:
return render_template("index.html", symbols=symbols, error_message=error_message)
plt.figure(figsize=(10, 6))
plt.plot(np.array(growth1.index), np.array(growth1.values), label=symbol1)
plt.plot(np.array(growth2.index), np.array(growth2.values), label=symbol2)
plt.xlabel("Year")
plt.ylabel("Value of $100 Investment")
plt.title("Stock Comparison")
plt.legend()
img = BytesIO()
plt.savefig(img, format='png')
img.seek(0)
img_base64 = base64.b64encode(img.getvalue()).decode('utf-8')
start_date = growth1.index[0].strftime('%Y-%m-%d')
end_date = growth1.index[-1].strftime('%Y-%m-%d')
final_value1 = growth1.values[-1]
final_value2 = growth2.values[-1]
comparison_message = (
f"On {start_date}, $100 invested in {symbol1} would be worth ${final_value1:.2f} on {end_date}.\n"
f"On {start_date}, $100 invested in {symbol2} would be worth ${final_value2:.2f} on {end_date}."
)
table_data = []
for year, val1, ret1, val2, ret2, cum_ret1, cum_ret2 in zip(
growth1.index.year,
growth1.values,
yearly_returns1.values,
growth2.values,
yearly_returns2.values,
cumulative_returns1,
cumulative_returns2
):
table_data.append({
"year": year,
"val1": val1,
"ret1": ret1,
"val2": val2,
"ret2": ret2,
"cum_ret1": cum_ret1,
"cum_ret2": cum_ret2
})
return render_template(
"result.html",
img_data=img_base64,
comparison_message=comparison_message,
table_data=table_data,
start_date=start_date,
end_date=end_date,
symbol1=symbol1,
symbol2=symbol2,
)
else:
symbols = fetch_stock_symbols('NASDAQ')
return render_template("index.html", symbols=symbols)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
answered 2 years ago
I understand it is not safe to share API but since the same not mission critical, sharing for easing troubleshooting. Will later delete this and generate another API key.
answered 2 years ago
Relevant content
asked 2 years ago
- AWS OFFICIALUpdated 2 months ago

Thanks! Updated the post with Amazon CLI error log screenshot.