I am trying to return matplotlib plots using pandas_datareader, matplotlib and Telegram. I have been studying the code here which covers a similar goal: Returning matplotlib plots using telegram bot but I am using a different technique with the telegram bot which does not align.
Mainly I am using update
and message.reply_photo
.
Docs for message.reply_photo
https://docs.pyrogram.org/api/bound-methods/Message.reply_photo
Here is my code for main.py:
#imports
def generate_chart(update, context):
stock = f'^GSPC'
start = datetime.date(2000, 1, 1)
end = datetime.date.today()
data = web.DataReader(stock, 'yahoo', start, end)
plot = data.plot(y='Open')
img_buf = BytesIO()
plt.savefig(img_buf, format='png')
prepared_data = img_buf
update.message.reply_photo(prepared_data)
def main():
updater = Updater(keys.API_KEY, use_context=True)
dp = updater.dispatcher
dp.add_handler(CommandHandler("stocks", generate_chart))
dp.add_handler(MessageHandler(Filters.text, handle_message))
dp.add_error_handler(error)
updater.start_polling()
updater.idle()
main()
I am generating a chart using pandas DataReader and then using a file-like BytesIO() object to assign an image buffer which I then try to send with update.message.reply_photo
.
The main error I am getting is:
UserWarning: Starting a Matplotlib GUI outside of the main thread will likely fail.
You may need to initialize matplotlib
with a non-interactive backend so it won't attempt to initiate a GUI to perform drawing.
Try putting this at the top of your script:
import matplotlib
matplotlib.use('agg')
# the rest of your code here
...
You can read more about matplotlib's backends here. The idea is that matplotlib will attempt to default into an interactive backend, which spawns a GUI. GUIs have issues being launched outside of the main thread since they themselves have their own event loop.
So, I believe you'll want to avoid the interactive backends to get this to work.