Miserlou / Zappa

Serverless Python
https://blog.zappa.io/
MIT License
11.89k stars 1.2k forks source link

TypeError: 'NoneType' object is not callable [Flask-Restful & Zappa] #1090

Closed MU-Software closed 6 years ago

MU-Software commented 7 years ago

Context

This occrs when I do zappa update dev and request to lambda site. But, when I locally run main.py without Zappa, this runs without any error. I'm currently using Flask and Flask-Restful. Of course, I update this on virtualenv named Circle-Backend

Expected Behavior

Returns proper JSON

Actual Behavior

Return error when I request to site,

"{'message': 'An uncaught exception happened while servicing this request. You can investigate this with the `zappa tail` command.','traceback': ['Traceback (most recent call last):\\n', '  File \"/var/task/handler.py\", line 448, in handler\\n    response = Response.from_app(self.wsgi_app, environ)\\n', '  File \"/var/task/werkzeug/wrappers.py\", line 903, in from_app\\n    return cls(*_run_wsgi_app(app, environ, buffered))\\n', '  File \"/var/task/werkzeug/wrappers.py\", line 57, in _run_wsgi_app\\n    return _run_wsgi_app(*args)\\n', '  File \"/var/task/werkzeug/test.py\", line 884, in run_wsgi_app\\n    app_rv = app(environ, start_response)\\n', \"TypeError: 'NoneType' object is not callable\\n\"]}"

or

"{'message': 'An uncaught exception happened while servicing this request. You can investigate this with the `zappa tail` command.', 'traceback': ['Traceback (most recent call last):\\n', '  File \"/var/task/handler.py\", line 448, in handler\\n    response = Response.from_app(self.wsgi_app, environ)\\n', '  File \"/var/task/werkzeug/wrappers.py\", line 903, in from_app\\n    return cls(*_run_wsgi_app(app, environ, buffered))\\n', '  File \"/var/task/werkzeug/test.py\", line 884, in run_wsgi_app\\n    app_rv = app(environ, start_response)\\n', \"TypeError: 'NoneType' object is not callable\\n\"]}"

Sometime First one returned, but mostly Second one returns.

On zappa tail

[1504870750832] Instancing..
[1504870751849] module 'main' has no attribute 'flask_app': AttributeError
Traceback (most recent call last):
  File "/var/task/handler.py", line 505, in lambda_handler
  return LambdaHandler.lambda_handler(event, context)
  File "/var/task/handler.py", line 239, in lambda_handler
  handler = cls()
  File "/var/task/handler.py", line 134, in __init__
  wsgi_app_function = getattr(self.app_module, self.settings.APP_FUNCTION)
AttributeError: module 'main' has no attribute 'flask_app'

And on CloudWatch

module 'main' has no attribute 'flask_app': AttributeError
Traceback (most recent call last):
File "/var/task/handler.py", line 505, in lambda_handler
return LambdaHandler.lambda_handler(event, context)
File "/var/task/handler.py", line 239, in lambda_handler
handler = cls()
File "/var/task/handler.py", line 134, in __init__
wsgi_app_function = getattr(self.app_module, self.settings.APP_FUNCTION)
AttributeError: module 'main' has no attribute 'flask_app'

Possible Fix

Unknown, I really want this 😛

Steps to Reproduce

  1. Do zappa update dev
  2. ?
  3. PROFIT!

Your Environment

class hello_world(Resource): def get(self): return { 'hello' : 'world' }

if name == 'main': flask_app = Flask(name) api = Api(flask_app)

import modules.rest_api
import importlib, glob, os
f_lst = glob.glob(
            os.path.join('modules', 'rest_api', '**', '*.py'),
            recursive=True)
f_lst = [z.replace('\\', '/').split('/')[2:]\
            for z in f_lst if '__init__' not in z]
if not SET_DEBUG_MOD: f_lst = [z for z in f_lst if 'test' not in z]
for z in f_lst:
    tgt_mod_pth = 'modules.rest_api.' + '.'.join(z)[:-3]
    tgt_mod = importlib.import_module(tgt_mod_pth, modules.rest_api)
    for y in tgt_mod.router_dict:
        route_path = '/{0}/{1}'.format('/'.join(z[:-1]), y).replace('//', '/')
        #print(route_path)
        api.add_resource(tgt_mod.router_dict[y], route_path)

api.add_resource(hello_world, '/')
flask_app.run(debug = SET_DEBUG_MOD)
zaraken commented 7 years ago

When you run the code as lambda it does not go into the if main block and flask_app is therefore undefined. Why don't you look at some of the example projects? https://github.com/Miserlou/Zappa/blob/master/example/app.py

mcrowson commented 7 years ago

The only thing that should be in the name==main section is the flask_app.run(debug = SET_DEBUG_MOD) line. If you put everything else in the main body of the file it would work.

MU-Software commented 7 years ago

Oops, Sorry for the late 🙏 That solved the problem, Thank you!

...And this is just out of curiosity, Is there any way to get event and context arguments when i get a normal request, not only on AWS events?

gadkaridarshan commented 7 years ago

I have the same issue. I do not have the main block since lambda does not go into it.

I have code in init.py and my class is in another file.

Can anyone please help? I am clueless because this is my first time trying out lambda and zappa.

Here is my init.py: from flask import Flask, jsonify, request from flasgger import Swagger from rulesEnginePy.RiskOfCancellation.RiskOfCancellation import RiskOfCancellation from logging.handlers import RotatingFileHandler import logging from datetime import datetime

app = Flask(name) Swagger(app, template={ 'swagger': '2.0', 'info': { 'title': 'RRRE RofCXL API', 'description': 'API for RRRE (Right Revenue Rules Engine) RofCXL (Risk of Cancellation)', }, 'basepath': '/api', })

log_handler = RotatingFileHandler(app.root_path + '/../logs/rrre.log', maxBytes=10000000, backupCount=10) log_handler.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s | %(pathname)s:%(lineno)d | %(funcName)s | %(levelname)s | %(message)s') log_handler.setFormatter(formatter) app.logger.addHandler(log_handler)

@app.route('/api//calculate/4', methods=['GET']) def calculate4(name): try: app.logger.info('About to use service %s' % name) sampleDate = datetime.strptime(request.args.get('date'), '%Y-%m-%d')

for id, sample in samples.items():

    WOM = calculators[name].week_of_month(sampleDate)
    DOW = sampleDate.weekday()+1
    riskOfCancellation = calculators[name].calculateRiskOfCancellationMOYDOW(int(sampleDate.month),int(DOW))
    app.logger.info(
        'Calculated Risk of Cancellation {0} for DOM {1}, DOW {2}, WOM {3} and MOY {4}'.format(
            riskOfCancellation,
            sampleDate.day,
            DOW,
            WOM,
            sampleDate.month
        )
        )
    calculations = {
        'DOM': sampleDate.day,
        'DOW': DOW,
        'WOM': WOM,
        'MOY': sampleDate.month,
        'riskOfCancellation': riskOfCancellation
        }
    app.logger.info('Done making calculations for request for calculate 4')
    return jsonify({
        'data': calculations,
    })
except KeyError:
    return jsonify({
        'errors': [{
            'code': '1000',
            'title': 'A service with the given name doesn\'t exist',
        }],
    }), 404

FYI - The above code works great on local machine (Vagrant, venv, Python 3.6, Flask).

Thanks for all your help Darshan

gadkaridarshan commented 7 years ago

Here is what I found in zappa tail: [1508966987748] Failed to find library...right filename? [1508966987749] No module named 'rulesEngine': ModuleNotFoundError Traceback (most recent call last): File "/var/task/handler.py", line 511, in lambda_handler return LambdaHandler.lambda_handler(event, context) File "/var/task/handler.py", line 239, in lambda_handler handler = cls() File "/var/task/handler.py", line 131, in init self.app_module = importlib.import_module(self.settings.APP_MODULE) File "/var/lang/lib/python3.6/importlib/init.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "", line 978, in _gcd_import File "", line 961, in _find_and_load File "", line 936, in _find_and_load_unlocked File "", line 205, in _call_with_frames_removed File "", line 978, in _gcd_import File "", line 961, in _find_and_load File "", line 948, in _find_and_load_unlocked ModuleNotFoundError: No module named 'rulesEngine'

The code works great on local machine. Not sure why the module is getting named 'rulesEngine'. It should have been 'rulesEnginePy'.

Thanks Darshan

gadkaridarshan commented 7 years ago

Issue resolved. In zappa settings json, I had 'rulesEngine' instead of 'rulesEnginePy'.

Thanks

piraka9011 commented 5 years ago

Just a quick note if anyone comes across this as well is to make sure your virtualenv name isn't the same as your app.

zaraken commented 5 years ago

Just a quick note if anyone comes across this as well is to make sure your virtualenv name isn't the same as your app.

If that breaks things for you, you should probably report it as a bug

gbartosz commented 5 years ago

I had a similar issue and resolved it by deleting all *.pyc files in my project directory. Must have had some old stuff in there that zappa used while building package.

jobu9395 commented 1 year ago

Thanks for posting this! I had the same issue of defining a model object in my if __name__ == '__main__': block.