azure function app python module import failure - python-3.x

I'm not able to execute my cloud function due to failures to import modules, module azure-identity for example, it's telling me module not found, I had my requirements.txt file:
msrestazure
azure-identity
azure.keyvault.secrets
azure-cli
and my code imports:
import logging
import json
import base64
import azure.functions as func
import requests
from azure.identity import AzureCliCredential
from azure.mgmt.resource import ResourceManagementClient
from azure.mgmt.network import NetworkManagementClient
from azure.mgmt.compute import ComputeManagementClient
import os
Result: Failure Exception: ModuleNotFoundError: No module named 'azure.identity'. Troubleshooting Guide: https://aka.ms/functions-modulenotfound Stack: File "/azure-functions-host/workers/python/3.6/LINUX/X64/azure_functions_worker/dispatcher.py", line 318, in _handle__function_load_request func_request.metadata.entry_point) File "/azure-functions-host/workers/python/3.6/LINUX/X64/azure_functions_worker/utils/wrappers.py", line 42, in call raise extend_exception_message(e, message) File "/azure-functions-host/workers/python/3.6/LINUX/X64/azure_functions_worker/utils/wrappers.py", line 40, in call return func( * args, ** kwargs) File "/azure-functions-host/workers/python/3.6/LINUX/X64/azure_functions_worker/loader.py", line 85, in load_function mod = importlib.import_module(fullmodname) File "/usr/local/lib/python3.6/importlib/init.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "/home/site/wwwroot/dworkerfn/init.py", line 6, in from azure.identity import AzureCliCredential**
My files hierarchy:
├── dworkerfn
│   ├── function.json
│   ├── __init__.py
│   ├── launch-worker.sh
│   └── sample.dat
├── host.json
└── requirements.txt
This issue is not related to the module itself, I tried with different modules, requests for example and always the same issue.

Related

Import all libraries from Python package in pantsbuild

I want to import all the resources in my models/sources directory, into another target in pants build my contents of root/models/sources:
├── base.py
├── BUILD
├── design.py
├── email.py
├── __init__.py
└── project_management.py
The contents of my build file are as follows:
python_library(
name="base",
sources=["base.py"],
dependencies=["root/models/tokens/__init__.py:__init__"]
)
python_library(
name="design",
sources=["design.py"],
dependencies=[":base"]
)
python_library(
name="email",
sources=["email.py"],
dependencies=[":base"]
)
python_library(
name="project_management",
sources=["project_management.py"],
dependencies=[
":base",
"root/models/tokens/__init__.py:__init__"
]
)
python_library(
name="__init__",
sources=["__init__.py"],
dependencies=[
":base",
":design",
":email",
":project_management"
]
)
Now in another target, I have an
from root.models.sources import *
How would I set up the dependencies of this other target to import all the libraries in models/sources ?
p.s I know using * is not best, but that's the simplest form. Also, init is a Factory.
import the init as long as it's a Factory that references all the other files in the package.
eg:
from root.models.sources.base import Source
from root.models.sources.design import DesignSource
from root.models.sources.email import EmailSource
from root.models.sources.project_management import \
ProjectManagementSource
def SourceFactory(source: str = "default"):
sources = {
"default": Source,
"foo1": ProjectManagementSource,
"foo2": ProjectManagementSource,
"foo3": ProjectManagementSource,
"foo4": ProjectManagementSource,
"foo5": ProjectManagementSource,
"foo6": ProjectManagementSource,
"foo7": ProjectManagementSource,
"foo8": EmailSource,
"foo9": DesignSource,
}
return sources[source] if source in sources.keys() else Source

Application Factory Pattern: AttributeError: 'tuple' object has no attribute 'shell_context_processor' [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I am trying to cast my Flask app into a App Factory Pattern, but I got stuck on the following error:
Traceback (most recent call last):
File "/usr/local/bin/flask", line 8, in <module>
sys.exit(main())
File "/usr/local/lib/python3.7/site-packages/flask/cli.py", line 967, in main
cli.main(args=sys.argv[1:], prog_name="python -m flask" if as_module else None)
File "/usr/local/lib/python3.7/site-packages/flask/cli.py", line 586, in main
return super(FlaskGroup, self).main(*args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "/usr/local/lib/python3.7/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/local/lib/python3.7/site-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/local/lib/python3.7/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/click/decorators.py", line 73, in new_func
return ctx.invoke(f, obj, *args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/flask/cli.py", line 848, in run_command
app = DispatchingApp(info.load_app, use_eager_loading=eager_loading)
File "/usr/local/lib/python3.7/site-packages/flask/cli.py", line 305, in __init__
self._load_unlocked()
File "/usr/local/lib/python3.7/site-packages/flask/cli.py", line 330, in _load_unlocked
self._app = rv = self.loader()
File "/usr/local/lib/python3.7/site-packages/flask/cli.py", line 388, in load_app
app = locate_app(self, import_name, name)
File "/usr/local/lib/python3.7/site-packages/flask/cli.py", line 240, in locate_app
__import__(module_name)
File "/home/chrdina/python/werda/werda.py", line 7, in <module>
#app.shell_context_processor
AttributeError: 'tuple' object has no attribute 'shell_context_processor'
I tried to find out where the AttributeError happens, but I'm totally stuck. I don't unterstand where the mentioned tuple is located in my code. I tried deleting the shell_context_processor part, but then the app seems to not know it's an app at all and throws this "Error: Failed to find Flask application or factory in module "werda". Use "FLASK_APP=werda:name to specify one.").
If I then try to export FLASK_APP again (it's already set in my .flaskenv) nothing changes.
I define the shell_context_processor in my werda.py (which is my app) in the top level of my directory.
werda.py:
from app import create_app, db
from app.models import User, Role, Employee, Language, Employee_Languages, Attendance, AttendanceArchive
app = create_app()
#app.shell_context_processor
def make_shell_context():
return {'db': db, 'User': User, 'Role': Role, 'Employee':Employee, 'Language':Language, 'Employee_Languages':Employee_Languages, 'Attendance':Attendance, 'AttendanceArchive':AttendanceArchive}
init.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_admin import Admin
from flask_bootstrap import Bootstrap
from flask_security import Security, SQLAlchemyUserDatastore
from flask_mail import Mail
import logging
from logging.handlers import SMTPHandler, RotatingFileHandler
import os
from config import Config
db = SQLAlchemy()
migrate = Migrate()
bootstrap = Bootstrap()
from app.models import User, Role
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security()
mail = Mail()
admin = Admin()
def create_app(config_class=Config):
app=Flask(__name__)
app.config.from_object(Config)
db.init_app(app)
migrate.init_app(app, db)
from app.models import User, Role
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security.init_app(app, user_datastore)
bootstrap.init_app(app)
mail.init_app(app)
app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'
from app.errors import bp as errors_bp
app.register_blueprint(errors_bp)
from app.main import bp as main_bp
app.register_blueprint(main_bp)
admin = Admin(app, name='werda', template_mode='bootstrap3')
#send errors via mail:
if not app.debug:
if app.config['MAIL_SERVER']:
auth = None
if app.config['MAIL_USERNAME'] or app.config['MAIL_PASSWORD']:
auth = (app.config['MAIL_USERNAME'], app.config['MAIL_PASSWORD'])
secure = None
if app.config['MAIL_USE_TLS']:
secure = ()
mail_handler = SMTPHandler(
mailhost=(app.config['MAIL_SERVER'], app.config['MAIL_PORT']),
fromaddr='no-reply#' + app.config['MAIL_SERVER'],
toaddrs=app.config['ADMINS'], subject='werda Failure',
credentials=auth, secure=secure)
mail_handler.setLevel(logging.ERROR)
app.logger.addHandler(mail_handler)
#save errors to log file:
if not os.path.exists('logs'):
os.mkdir('logs')
file_handler = RotatingFileHandler('logs/werda.log', maxBytes=10240,
backupCount=10)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('werda startup')
return app, admin
from app import models
Directory Structure
.
├── app
│   ├── cli.py
│   ├── errors
│   │   ├── handlers.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── main
│   │   ├── forms.py
│   │   ├── __init__.py
│   │   ├── __pycache__
│   │   └── routes.py
│   ├── models.py
│   └── templates
│   ├── addnextweek.html
│   ├── base.html
│   ├── errors
│   │   ├── 403.html
│   │   ├── 404.html
│   │   └── 500.html
│   ├── index.html
│   ├── movetoarchive.html
│   ├── nextweek.html
│   ├── now.html
│   ├── russ.html
│   ├── security
│   │   ├── login_user.html
│   │   └── register_user.html
│   ├── thisweek.html
│   ├── thisweek_working.html
│   └── today.html
├── app.db
├── config.py
├── libc6_2.31-0ubuntu8+lp1871129~1_amd64.deb
├── README.md
├── requirements.txt
├── werda.py
Consider to use the init_app() function in your factory function. You also should modify your app.config.from_object(Config) to app.config.from_object(class_config)
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_admin import Admin
from flask_bootstrap import Bootstrap
from flask_security import Security, SQLAlchemyUserDatastore
from flask_mail import Mail
import logging
from logging.handlers import SMTPHandler, RotatingFileHandler
import os
from config import Config
from app.models import User, Role #<-----------repositioned
db = SQLAlchemy()
migrate = Migrate()
bootstrap = Bootstrap()
user_datastore = SQLAlchemyUserDatastore() #<-------------modified
security = Security()
mail = Mail()
admin = Admin()
def create_app(config_class=Config):
app=Flask(__name__)
app.config.from_object(class_config) #<------modified
db.init_app(app)
migrate.init_app(app, db)
user_datastore.init_app = SQLAlchemyUserDatastore(app, db, User, Role) #<-------modified
security.init_app(app, user_datastore)
bootstrap.init_app(app)
mail.init_app(app)
app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'
from app.errors import bp as errors_bp
app.register_blueprint(errors_bp)
from app.main import bp as main_bp
app.register_blueprint(main_bp)
admin = Admin(app, name='werda', template_mode='bootstrap3')
#send errors via mail:
if not app.debug:
if app.config['MAIL_SERVER']:
auth = None
if app.config['MAIL_USERNAME'] or app.config['MAIL_PASSWORD']:
auth = (app.config['MAIL_USERNAME'], app.config['MAIL_PASSWORD'])
secure = None
if app.config['MAIL_USE_TLS']:
secure = ()
mail_handler = SMTPHandler(
mailhost=(app.config['MAIL_SERVER'], app.config['MAIL_PORT']),
fromaddr='no-reply#' + app.config['MAIL_SERVER'],
toaddrs=app.config['ADMINS'], subject='werda Failure',
credentials=auth, secure=secure)
mail_handler.setLevel(logging.ERROR)
app.logger.addHandler(mail_handler)
#save errors to log file:
if not os.path.exists('logs'):
os.mkdir('logs')
file_handler = RotatingFileHandler('logs/werda.log', maxBytes=10240,
backupCount=10)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('werda startup')
return app, admin
from app import models
I got it!
I return'ed app and admin in create_app(), which caused the problem. And it seems that's also where the mysterious Tuple was situated.
If create_app() only return's app my app starts as it should. Now to work out how to run flask-admin correctly.
Corrected code for now:
init.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_admin import Admin
from flask_bootstrap import Bootstrap
from flask_security import Security, SQLAlchemyUserDatastore
from flask_mail import Mail
import logging
from logging.handlers import SMTPHandler, RotatingFileHandler
import os
from config import Config
db = SQLAlchemy()
migrate = Migrate()
bootstrap = Bootstrap()
from app.models import User, Role
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security()
mail = Mail()
admin = Admin()
def create_app(config_class=Config):
app=Flask(__name__)
app.config.from_object(Config)
db.init_app(app)
migrate.init_app(app, db)
from app.models import User, Role
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security.init_app(app, user_datastore)
bootstrap.init_app(app)
mail.init_app(app)
app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'
from app.errors import bp as errors_bp
app.register_blueprint(errors_bp)
from app.main import bp as main_bp
app.register_blueprint(main_bp)
admin = Admin(app, name='werda', template_mode='bootstrap3')
#send errors via mail:
if not app.debug:
if app.config['MAIL_SERVER']:
auth = None
if app.config['MAIL_USERNAME'] or app.config['MAIL_PASSWORD']:
auth = (app.config['MAIL_USERNAME'], app.config['MAIL_PASSWORD'])
secure = None
if app.config['MAIL_USE_TLS']:
secure = ()
mail_handler = SMTPHandler(
mailhost=(app.config['MAIL_SERVER'], app.config['MAIL_PORT']),
fromaddr='no-reply#' + app.config['MAIL_SERVER'],
toaddrs=app.config['ADMINS'], subject='werda Failure',
credentials=auth, secure=secure)
mail_handler.setLevel(logging.ERROR)
app.logger.addHandler(mail_handler)
#save errors to log file:
if not os.path.exists('logs'):
os.mkdir('logs')
file_handler = RotatingFileHandler('logs/werda.log', maxBytes=10240,
backupCount=10)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('werda startup')
return app #deleted admin here
from app import models

The run time error by import python module

I am trying to make correctly import the function "mmenu" from another module
I got a run time error:
Traceback (most recent call last):
File "path.../venv/src/routes.py", line 4, in <module>
from venv.src.main_menu import mmenu
ModuleNotFoundError: No module named 'venv.src'
after Java this Python is a bit of a mystery to me :)
I have 2 files in the same "src" directory
main_menu.py
def mmenu():
menu = [{"name": "HOME", "url": "home"},
{"name": "fooo", "url": "foo"},
{"name": "bar", "url": "bar"},
{"name": "CONTACT", "url": "contact"}]
return menu
routes.py
from flask import Flask, render_template, request, flash, session, redirect, abort
from jinja2 import Template
from flask.helpers import url_for
from venv.src.main_menu import mmenu
app = Flask(__name__)
menu = mmenu
#app.route("/")
#app.route("/index")
def index():
# return "index"
print("loaded" + url_for('index'))
return render_template('index.html', title="Index page", menu=menu)
# ...
if __name__ == "__main__":
app.run(debug=True)
import was generated by IDE like:
from venv.src.parts.main_menu import mmenu
Your IDE (which IDE?) is likely misconfigured if it generates imports like that.
The venv itself, nor any src directory within them, shouldn't be within import paths.
You never mention you have a parts/ package, but from the import I'll assume you do, and your structure is something like
venv/
src/ # source root
routes.py
parts/ # parts package
__init__.py # (empty) init for parts package
main_menu.py
With this structure, main_menu is importable as parts.main_menu from routes.py assuming you start the program with python routes.py.
If you have __init__.py files in venv/ and/or src/, get rid of them; you don't want those directories to be assumed to be Python packages.

AWS SAM Nested Application in Python with Dynamorm

I am using AWS SAM to build a Serverless application. I followed the instruction to build a nested application.
My application structure is basically the following:
.
├── MAKEFILE
├── README.md
├── __init__.py
├── apps
│ ├── __init__.py
│ ├── account
│ │ ├── __init__.py
│ │ ├── endpoints.py
│ │ ├── models.py
│ │ ├── requirements.txt
│ │ └── template.yaml
├── samconfig.toml
└── template.yaml
The requirements.txt in the folder apps/account/ has the following python packages: boto3 marshmallow and dynamorm.
The sam build and sam deploy works fine and the lambda functions are deployed correctly. However, I receive an error when calling the lambda function. The logs show the following error Unable to import module 'endpoints': No module named 'dynamorm'.
Here are excerpts from my code:
endpoints.py
import json
import boto3
from models import Account
print('Loading function')
def account_info(event, context):
apiKey = event["requestContext"]["identity"]["apiKeyId"]
account_info = Account.get(id= apiKey)
return {
"statusCode": 200,
"body": json.dumps(account_info)
}
models.py
import datetime
from dynamorm import DynaModel, GlobalIndex, ProjectAll
from marshmallow import Schema, fields, validate, validates, ValidationError
class Account(DynaModel):
# Define our DynamoDB properties
class Table:
name = 'XXXXXXXXXX'
hash_key = 'id'
read = 10
write = 5
class Schema:
id = fields.String(required=True)
name = fields.String()
email = fields.String()
phonenumber = fields.String()
status = fields.String()
I am not sure what am I missing? Are there additional instructions to build a nested app in SAM?
Thank you so much for the help!
According to https://github.com/awslabs/aws-sam-cli/issues/1213, this feature is not supported yet.
In my case, I did 'sam build' on every nested stacks and fix parent yaml template as following (use template.yaml generated by sam build command), then works. But just workaround and not nice way.
XXX_APP:
Type: AWS::Serverless::Application
Properties:
Location: nest_application/.aws-sam/build/template.yaml

Error on deploying Python app to AWS Lambda

I have built a Python-Tornado app and am trying to deploy it to AWS Lambda using zappa. But, I am getting an error Error: Warning! Status check on the deployed lambda failed. A GET request to '/' yielded a 502 response code.
My folder structure inside the root folder is :
├── amortization.py
├── config.py
├── dmi-amort-dev-1557138776.zip
├── main.py
├── requirements.txt
├── venv
│   ├── bin
│  
└── zappa_settings.json
zappa deploy dev gives me :
Calling deploy for stage dev..
Downloading and installing dependencies..
- pandas==0.24.2: Using locally cached manylinux wheel
- numpy==1.16.3: Using locally cached manylinux wheel
- sqlite==python3: Using precompiled lambda package
Packaging project as zip.
Uploading dmi-amort-dev-1557143681.zip (30.8MiB)..
100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 32.3M/32.3M [00:19<00:00, 1.94MB/s]
Scheduling..
Scheduled dmi-amort-dev-zappa-keep-warm-handler.keep_warm_callback with expression rate(4 minutes)!
Uploading dmi-amort-dev-template-1557143718.json (1.5KiB)..
100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1.56K/1.56K [00:00<00:00, 10.6KB/s]
Waiting for stack dmi-amort-dev to create (this can take a bit)..
75%|█████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 3/4 [00:09<00:04, 5.00s/res]
Deploying API Gateway..
Error: Warning! Status check on the deployed lambda failed. A GET request to '/' yielded a 502 response code.
zappa tail gives me
Traceback (most recent call last):
File "/var/task/handler.py", line 602, in lambda_handler
return LambdaHandler.lambda_handler(event, context)
File "/var/task/handler.py", line 245, in lambda_handler
handler = cls()
File "/var/task/handler.py", line 142, in __init__
wsgi_app_function = getattr(self.app_module, self.settings.APP_FUNCTION)
AttributeError: module 'main' has no attribute 'app'
zappa_settings.json:
{
"dev": {
"app_function": "main.app",
"aws_region": "ap-south-1",
"profile_name": "default",
"project_name": "dmi-amort",
"runtime": "python3.6",
"s3_bucket": "zappa-mekp457ye",
"manage_roles": false,
"role_name": "lambda-role",
}
}
main.py:
import tornado.web
from tornado.ioloop import IOLoop
from tornado.web import MissingArgumentError
from config import get_arguments
from amortization import get_amort_schedule
class MainHandler(tornado.web.RequestHandler):
def prepare(self):
"""Checking if all the required parameters are present."""
if self.request.method != 'POST':
self.write_error(status_code=405, message="Method not allowed")
return
self.parameters = dict()
for key in get_arguments():
try:
self.parameters[key] = self.get_argument(key)
except MissingArgumentError:
self.write_error(status_code=400,
message="Missing Argument(s)")
return
# checking if 'label' is provided
if 'label' in self.request.arguments.keys():
self.parameters['label'] = self.get_argument('label')
# Set up response dictionary.
self.response = dict()
def get(self, *args, **kwargs):
self.write_error(status_code=405, message="Method not allowed")
def post(self, *args, **kwargs):
"""Executes the main logic part."""
self.response = get_amort_schedule(self.parameters)
self.write_json()
def set_default_headers(self):
"""Sets content-type as 'application/json' for response as JSON."""
self.set_header('Content-Type', 'application/json')
def write_error(self, status_code, **kwargs):
"""Invokes when error occurs in processing the request."""
if 'message' not in kwargs:
if status_code == 405:
kwargs['message'] = 'Invalid HTTP method.'
else:
kwargs['message'] = 'Unknown error.'
kwargs["error"] = True
self.set_status(status_code=status_code)
self.response = dict(kwargs)
self.write_json()
def write_json(self):
"""Responsible for writing the response."""
if "status" in self.response:
self.set_status(self.response.get("status"))
self.set_default_headers()
self.write(self.response)
self.finish()
def main():
app = tornado.web.Application([
(r'/', MainHandler),
], debug=True)
# server = HTTPServer(app)
# server.bind(8888)
# server.start(0)
app.listen()
# app.run(host='0.0.0.0')
IOLoop.current().start()
if __name__ == '__main__':
main()
What is the mistake here and how can I fix it?
It looks like the deployment is succeeding, but when Zappa checks to see if the code is working, the return code is 502, which suggests that the lambda function is failing to run in the lambda environment.
Taking a look at the logs, the critical line is:
AttributeError: module 'main' has no attribute 'app'
And this is true, if we look at your code, at no point do you expose an attribute called app in main.py.
I'm not experienced with Tornado, but I suspect that if you move the declaration of app out of the main() function and into the root scope, then the handler should succeed.
For example:
# rest of the file...
self.finish()
app = tornado.web.Application([
(r'/', MainHandler),
], debug=True)
app.listen()
def main():
IOLoop.current().start()
if __name__ == '__main__':
main()

Resources