Reputation: 33
App Structure
The other modules used by app.py reference some additional modules via import that are to be installed by requirements.txt such as pyyaml and sqlparse.
Here is a snippet from the pipeline yaml that installs these during the build in Azure DevOps
- task: Bash@3
displayName: 'Install Python dependencies'
inputs:
targetType: 'inline'
script: |
python3.9 -m venv antenv
source antenv/bin/activate
pip3 install --upgrade pip
pip3 install --upgrade setuptools
pip3 install --upgrade setuptools_rust
pip3 install uamqp --upgrade --no-cache-dir
pip3 install -r requirements.txt --upgrade --no-cache-dir
When I run the build pipeline in Azure DevOps, I can see the modules getting installed fine. Here is when things get weird...
When I execute the release pipeline, the release fails and in the logs for the Azure Web App, I can see a 'ModuleNotFound' error....'No module named yaml'. This is due to one of my py files using an 'import yaml' statement - so it appears it is not finding the pyyaml module.
Upon running 'pip3 list', I do not see pyyaml installed. So then I commented out 'import yaml' in my py file and deployed the release, it was successful. I did this so I could SSH into the Web App to do some inspecting. However, when I drill down in the virtual environment directory (antenv), I can see the modules installed there (/home/site/wwwroot/antenv/lib/python3.9/site-packages/). When I open a Python shell, and try to do an 'import yaml', I see that module not found error there as well.
I checked around the web and I did find people mentioning you need to configure an app setting on the Azure Web App, SCM_DO_BUILD_DURING_DEPLOYMENT and set that to 'true' or '1' - which I made sure to do beforehand.
This is where it gets even more odd, just as a test, I copied the actual 'yaml' directory (pyyaml module folder for the pyyaml install) to the app.py root level, then did a build/release again, and it deployed fine....even with the 'import yaml' uncommented in one of my .py files!! The app is even functional! Also, running 'pip3 list' within the Web App STILL does not show pyyaml as installed!!
Anyone know what the issue could be? Spent days trying to get this to work....copying every additional non-OOTB Python module to the root of my repo along-side app.py cannot possibly be the feasible solution right?
Upvotes: 1
Views: 630
Reputation: 8157
Make sure you add PYyaml in requirements.txt
like below for the import statement in the app.py to work, Given requirements.txt
is in the root folder:-
app.py to load config.yaml:-
import os
from flask import (Flask, redirect, render_template, request,
send_from_directory, url_for)
import yaml
app = Flask(__name__)
# Define a global variable to store the loaded YAML data
config = None
def load_config():
global config
try:
with open('config.yaml', 'r') as config_file:
config = yaml.load(config_file, Loader=yaml.FullLoader)
except FileNotFoundError:
print('Config file not found.')
# Load the configuration when the app starts
load_config()
@app.route('/')
def index():
print('Request for index page received')
return render_template('index.html')
@app.route('/favicon.ico')
def favicon():
return send_from_directory(os.path.join(app.root_path, 'static'),
'favicon.ico', mimetype='image/vnd.microsoft.icon')
@app.route('/hello', methods=['POST'])
def hello():
name = request.form.get('name')
if name:
print('Request for hello page received with name=%s' % name)
return render_template('hello.html', name=name, config=config)
else:
print('Request for hello page received with no name or blank name -- redirecting')
return redirect(url_for('index'))
if __name__ == '__main__':
app.run()
requirements.txt:-
Flask==2.0.2
gunicorn
PyYAML
My yaml pipeline:-
trigger:
- main
variables:
azureServiceConnectionId: 'xxxxxxxxxxxxx0b035'
webAppName: 'siliconwebapp098'
vmImageName: 'ubuntu-latest'
environmentName: 'siliconwebapp098'
projectRoot: $(System.DefaultWorkingDirectory)
pythonVersion: '3.7'
stages:
- stage: Build
displayName: Build stage
jobs:
- job: BuildJob
pool:
vmImage: $(vmImageName)
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '$(pythonVersion)'
displayName: 'Use Python $(pythonVersion)'
- script: |
python -m venv antenv
source antenv/bin/activate
python -m pip install --upgrade pip
pip install setup
pip install -r requirements.txt
workingDirectory: $(projectRoot)
displayName: "Install requirements"
- task: ArchiveFiles@2
displayName: 'Archive files'
inputs:
rootFolderOrFile: '$(projectRoot)'
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
replaceExistingArchive: true
- upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
displayName: 'Upload package'
artifact: drop
- stage: Deploy
displayName: 'Deploy Web App'
dependsOn: Build
condition: succeeded()
jobs:
- deployment: DeploymentJob
pool:
vmImage: $(vmImageName)
environment: $(environmentName)
strategy:
runOnce:
deploy:
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '$(pythonVersion)'
displayName: 'Use Python version'
- task: AzureWebApp@1
displayName: 'Deploy Azure Web App : siliconwebapp098'
inputs:
azureSubscription: $(azureServiceConnectionId)
appName: $(webAppName)
package: $(Pipeline.Workspace)/drop/$(Build.BuildId).zip
Installed requirements.txt with this task:-
- script: |
python -m venv antenv
source antenv/bin/activate
python -m pip install --upgrade pip
pip install setup
pip install -r requirements.txt
workingDirectory: $(projectRoot)
displayName: "Install requirements"
Upvotes: 0