As @motrobol mentioned, multiple legends are the way to go. You can align each legend using the domain of corresponding yaxis:
for i, yaxis in enumerate(fig.select_yaxes(), 1):
legend_name = f"legend{i}"
fig.update_layout({legend_name: dict(y=yaxis.domain[1], yanchor="top")}, showlegend=True)
fig.update_traces(row=i, legend=legend_name)
Modifying Subplots in Python with the snippet above:
from plotly.subplots import make_subplots
import plotly.graph_objects as go
fig = make_subplots(rows=3, cols=1)
fig.append_trace(go.Scatter(
x=[3, 4, 5],
y=[1000, 1100, 1200],
), row=1, col=1)
fig.append_trace(go.Scatter(
x=[2, 3, 4],
y=[100, 110, 120],
), row=2, col=1)
fig.append_trace(go.Scatter(
x=[0, 1, 2],
y=[10, 11, 12]
), row=3, col=1)
fig.update_layout(height=600, width=600, title_text="Stacked Subplots")
for i, yaxis in enumerate(fig.select_yaxes(), 1):
legend_name = f"legend{i}"
fig.update_layout({legend_name: dict(y=yaxis.domain[1], yanchor="top")}, showlegend=True)
fig.update_traces(row=i, legend=legend_name)
fig.show()