Flask object has no attribute app_context - python

I'm trying to send emails periodically with flask mail, but I'm stuck with this error: Flask object has no attribute app_context
def mail_periodic():
print "sending mail at " +time.ctime()
app = current_app._get_current_object()
msg = Message("no-reply: Avantgarde.Rentals",
sender="avantgarde.rentals.noreply#gmail.com",
)
msg.add_recipient('aladinne.k#gmail.com')
msg.body = 'Email periodic '
mail2 = Mail(app)
with app.app_context():
mail2.send(msg)
print"email sent "
threading.Timer(5, mail_periodic).start()
#app.route('/startcronemailing')
def startcronemailing():
try:
mail_periodic()
except Exception, exception:
return exception.message
return "crone mailing started"
the exception that i got :
Exception in thread Thread-3:
Traceback (most recent call last):
File "C:\Python27\lib\threading.py", line 801, in __bootstrap_inner
self.run()
File "C:\Python27\lib\threading.py", line 1073, in run
self.function(*self.args, **self.kwargs)
File "app.py", line 113, in mail_periodic
host_link='http://' + request.host,
File "C:\Python27\lib\site-packages\werkzeug\local.py", line 336, in __getattr__
return getattr(self._get_current_object(), name)
File "C:\Python27\lib\site-packages\werkzeug\local.py", line 295, in _get_current_object
return self.__local()
File "C:\Python27\lib\site-packages\flask\globals.py", line 19, in _lookup_object
raise RuntimeError('working outside of request context')
RuntimeError: working outside of request context
please note that even if i use another mailing service like sendgrid i got the same error

You have to pass app instance as args. If you use current_app._get_current_object() to get app instance inside target function, you will not get the right app in another thread. For example:
from threading import Thread
from flask import current_app
from flask_mail import Message
from bluelog.extensions import mail
def _send_async_mail(app, message): # target function
with app.app_context():
mail.send(message)
def send_async_mail(subject, to, html):
app = current_app._get_current_object() # get the real app instance
message = Message(subject, recipients=[to], html=html)
thr = Thread(target=_send_async_mail, args=[app, message]) # pass app
thr.start()
return thr

Related

AssertionError: View function mapping is overwriting an existing endpoint function: bot

Does anyone know why I'm getting this overwrite error? I only have two functions and have a single route that can't overwrite an existing endpoint function. I'm running python3 routes.py, thanks!
routes.py
from flask import request
from __init__ import app, _update_db
from models import User
from twilio.twiml.messaging_response import MessagingResponse
def _send_message(output_lines):
resp = MessagingResponse()
msg = resp.message()
msg.body("\n".join(output_lines))
return str(resp)
#app.route("/bot", methods=["POST", "GET"])
def bot():
output_lines = []
incoming_msg = request.values.get('Body', '').lower()
remote_number = request.values.get('From')
resp = MessagingResponse()
msg = resp.message()
responded = False
user = User.query.get(remote_number)
Traceback
Traceback (most recent call last):
File "routes.py", line 14, in <module>
#app.route("/bot", methods=["POST", "GET"])
File ".../Projects/wisdom/wisdom-venv/lib/python3.7/site-packages/flask/app.py", line 1315, in decorator
self.add_url_rule(rule, endpoint, f, **options)
File ".../Projects/wisdom/wisdom-venv/lib/python3.7/site-packages/flask/app.py", line 98, in wrapper_func
return f(self, *args, **kwargs)
File ".../Projects/wisdom/wisdom-venv/lib/python3.7/site-packages/flask/app.py", line 1284, in add_url_rule
"existing endpoint function: %s" % endpoint
AssertionError: View function mapping is overwriting an existing endpoint function: bot

How to solve 'request that this server could not understand' error?

I have built an API with Flask and keep getting an error when testing it with postman.
I only started getting this error when I added threading so that I could continue running my scraper after returning data to postman, now I'm not sure how to get past this issue
My code looks something like this:
from threading import Thread
from flask import Flask
application = Flask(__name__)
class Compute(Thread):
def __init__(self, request):
print("init")
Thread.__init__(self)
self.request = request
def run(self):
print("RUN")
command = './webscraper.py -us "{user}" -p "{password}" -url "{url}"'.format(**self.request.json)
output = subprocess.call(['bash','-c', command])
print("done")
#application.route('/scraper/run', methods=['POST'])
def init_scrape():
thread_a = Compute(request.__copy__())
thread_a.start()
return jsonify({'Scraping this site: ': request.json["url"]}), 201
if __name__ == '__main__':
application.run(host="0.0.0.0", port="8080")
My POST data is just a site url and details to login to it, looks something like this
data = {
{
"user":"username",
"password":"password",
"url":"www.mysite.com/"
}
If I make a POST request to localhost:8080/scraper/run with postman I get this error:
init
RUN
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "api_app.py", line 19, in run
command = './portal_scrape.py -us "{user}" -p "{password}" -start {start} -end {end} -fav "{favourite}" -url "{url}"'.format(**self.request.json)
File "/home/connor/Desktop/portal_dl/venv36/lib/python3.6/site-packages/flask/wrappers.py", line 47, in json
return self.get_json()
File "/home/connor/Desktop/portal_dl/venv36/lib/python3.6/site-packages/flask/wrappers.py", line 71, in get_json
data = self._get_data_for_json(cache=cache)
File "/home/connor/Desktop/portal_dl/venv36/lib/python3.6/site-packages/flask/wrappers.py", line 50, in _get_data_for_json
return self.get_data(cache=cache)
File "/home/connor/Desktop/portal_dl/venv36/lib/python3.6/site-packages/werkzeug/wrappers.py", line 514, in get_data
rv = self.stream.read()
File "/home/connor/Desktop/portal_dl/venv36/lib/python3.6/site-packages/werkzeug/wsgi.py", line 1307, in read
return self.on_disconnect()
File "/home/connor/Desktop/portal_dl/venv36/lib/python3.6/site-packages/werkzeug/wsgi.py", line 1275, in on_disconnect
raise ClientDisconnected()
werkzeug.exceptions.ClientDisconnected: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
I am sending the same POST request I had used when it was working without threading

Python Flask: RQ Worker raising KeyError because of environment variable

I'm trying to setup a redis queue and a worker to process the queue with my flask app. I'm implementing this to handle a task that sends emails. I'm a little confused because it appears that the stack trace is saying that my 'APP_SETTINGS' environment variable is not set when it is in fact set.
Prior to starting up the app, redis or the worker, I set APP_SETTINGS:
export APP_SETTINGS="project.config.DevelopmentConfig"
However, when an item gets added to the queue, here's the stack trace:
17:00:00 *** Listening on default...
17:00:59 default: project.email.sendMailInBG(<flask_mail.Message object at 0x7fc930e1c3d0>) (aacf9546-5558-4db8-9232-5f36c25d521b)
17:01:00 KeyError: 'APP_SETTINGS'
Traceback (most recent call last):
File "/home/tony/pyp-launch/venv/local/lib/python2.7/site-packages/rq/worker.py", line 588, in perform_job
rv = job.perform()
File "/home/tony/pyp-launch/venv/local/lib/python2.7/site-packages/rq/job.py", line 498, in perform
self._result = self.func(*self.args, **self.kwargs)
File "/home/tony/pyp-launch/venv/local/lib/python2.7/site-packages/rq/job.py", line 206, in func
return import_attribute(self.func_name)
File "/home/tony/pyp-launch/venv/local/lib/python2.7/site-packages/rq/utils.py", line 150, in import_attribute
module = importlib.import_module(module_name)
File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/home/tony/pyp-launch/project/__init__.py", line 24, in <module>
app.config.from_object(os.environ['APP_SETTINGS'])
File "/home/tony/pyp-launch/venv/lib/python2.7/UserDict.py", line 40, in __getitem__
raise KeyError(key)
KeyError: 'APP_SETTINGS'
Traceback (most recent call last):
File "/home/tony/pyp-launch/venv/local/lib/python2.7/site-packages/rq/worker.py", line 588, in perform_job
rv = job.perform()
File "/home/tony/pyp-launch/venv/local/lib/python2.7/site-packages/rq/job.py", line 498, in perform
self._result = self.func(*self.args, **self.kwargs)
File "/home/tony/pyp-launch/venv/local/lib/python2.7/site-packages/rq/job.py", line 206, in func
return import_attribute(self.func_name)
File "/home/tony/pyp-launch/venv/local/lib/python2.7/site-packages/rq/utils.py", line 150, in import_attribute
module = importlib.import_module(module_name)
File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/home/tony/pyp-launch/project/__init__.py", line 24, in <module>
app.config.from_object(os.environ['APP_SETTINGS'])
File "/home/tony/pyp-launch/venv/lib/python2.7/UserDict.py", line 40, in __getitem__
raise KeyError(key)
KeyError: 'APP_SETTINGS'
17:01:00 Moving job to u'failed' queue
17:01:00
17:01:00 *** Listening on default...
email.py
from flask.ext.mail import Message
from project import app, mail
from redis import Redis
from rq import use_connection, Queue
q = Queue(connection=Redis())
def send_email(to, subject, template, emailable):
if emailable==True:
msg = Message(
subject,
recipients=[to],
html=template,
sender=app.config['MAIL_DEFAULT_SENDER']
)
q.enqueue(sendMailInBG, msg)
else:
print("no email sent, emailable set to: " + str(emailable))
def sendMailInBG(msgContent):
with app.test_request_context():
mail.send(msgContent)
worker.py
import os
import redis
from rq import Worker, Queue, Connection
listen = ['default']
redis_url = os.getenv('REDISTOGO_URL', 'redis://localhost:6379')
conn = redis.from_url(redis_url)
if __name__ == '__main__':
with Connection(conn):
worker = Worker(list(map(Queue, listen)))
worker.work()
I'd really appreciate another set of eyes on this. I can't for the life of me figure out what's going on here.
Thanks to the prompting of #danidee, I discovered that the environment variables need to be defined in each terminal. Hence, APP_SETTINGS was defined for the actual app, but not for the worker.
The solution was to set APP_SETTINGS in the worker terminal.

Gunicorn throws KeyError resulting in Internal Server Error

In my flask app I have
app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024
class StreamConsumingMiddleware(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
stream = LimitedStream(environ['wsgi.input'], int(environ['CONTENT_LENGTH'] or 0))
environ['wsgi.input'] = stream
app_iter = self.app(environ, start_response)
try:
stream.exhaust()
for event in app_iter:
yield event
finally:
if hasattr(app_iter, 'close'):
app_iter.close()
app.wsgi_app = StreamConsumingMiddleware(app.wsgi_app)
When I simply run the app using python app.py it works as expected. However, launching with Gunicorn gunicorn app:app, the app starts just fine, but trying to load any page results in a 500, and throws a KeyError
[2015-11-08 17:36:53 -0500] [15848] [ERROR] Error handling request
Traceback (most recent call last):
File "[...]/venv/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 130, in handle
self.handle_request(listener, req, client, addr)
File "[...]/venv/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 176, in handle_request
for item in respiter:
File "[...]/app.py", line 33, in __call__
stream = LimitedStream(environ['wsgi.input'], int(environ['CONTENT_LENGTH'] or 0))
KeyError: 'CONTENT_LENGTH'
Any ideas?
You are accessing a key that doesn't exist. Python dictionaries provide a get method to help with this
int(os.environ.get('CONTENT_LENGTH', 0))
This will return the value of os.environ['CONTENT_LENGTH'] if the key exists or 0 if it doesn't.

Message instance has no attribute 'read' in Google app engine mail receive

Code in receive handler
class LogSenderHandler(InboundMailHandler):
def receive(self, mail_message):
logging.info("Received a message from: " + mail_message.sender)
#logging.info("Received a message from: " + mail_message.attachments)
logging.info("Received a message from: " + mail_message.date)
logging.info("Received a message from: " + mail_message.subject)
report = DocFile()
report.doc_name = mail_message.subject
if mail_message.attachments is not None:
report.doc_file = mail_message.attachments
else:
report.doc_file = mail_message.bodies(content_type='text/plain')
report.put()
application = webapp.WSGIApplication([LogSenderHandler.mapping()], debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
code in url.py
inbound_services:
- mail
handlers:
- url: /_ah/mail/.+
script: handle_incoming_email.py
error when i try to send a simple email from http://localhost:8080/_ah/admin/inboundmail
Message send failure
Traceback (most recent call last):
File "F:\Program Files\Google\google_appengine\google\appengine\ext\webapp\__init__.py", line 509, in __call__
handler.post(*groups)
File "F:\Program Files\Google\google_appengine\google\appengine\ext\webapp\mail_handlers.py", line 58, in post
self.receive(mail.InboundEmailMessage(self.request.body))
File "F:\Program Files\Google\google_appengine\google\appengine\api\mail.py", line 547, in __init__
self.update_from_mime_message(mime_message)
File "F:\Program Files\Google\google_appengine\google\appengine\api\mail.py", line 1081, in update_from_mime_message
mime_message = _parse_mime_message(mime_message)
File "F:\Program Files\Google\google_appengine\google\appengine\api\mail.py", line 232, in _parse_mime_message
return email.message_from_file(mime_message)
File "F:\Python25\lib\email\__init__.py", line 66, in message_from_file
return Parser(*args, **kws).parse(fp)
File "F:\Python25\lib\email\parser.py", line 68, in parse
data = fp.read(8192)
AttributeError: Message instance has no attribute 'read'
EDIT
This error comes only on local machine and not on app engine
Do you have the latest version of the API? for the incoming mail function need to be the 1.2.6 or greatest.
Later i saw in google groups the "solution" I quote Joshua Smith
"I've found that you need to restart the local dev environment before
doing any inbound mail testing. Otherwise, you'll get that read error"
So every time that you change your code you MUST restart the server, even if only add white spaces (seriously)

Categories

Resources