azureazure-web-app-servicebotframeworkazure-bot-serviceazure-webapps

Error deploying echo-bot.py on Azure. ModuleNotFoundError: No module named 'aiohttp'


I am following the Azure's tutorial on how to create and deploy a simple echo bot.

However, I have a problem when deploying. Here's the error:

2024-02-15T14:28:44.906911470Z    _____                               
2024-02-15T14:28:44.906996971Z   /  _  \ __________ _________   ____  
2024-02-15T14:28:44.907002071Z  /  /_\  \\___   /  |  \_  __ \_/ __ \ 
2024-02-15T14:28:44.907005571Z /    |    \/    /|  |  /|  | \/\  ___/ 
2024-02-15T14:28:44.907008971Z \____|__  /_____ \____/ |__|    \___  >
2024-02-15T14:28:44.907012571Z         \/      \/                  \/ 
2024-02-15T14:28:44.907015771Z A P P   S E R V I C E   O N   L I N U X
2024-02-15T14:28:44.907019271Z 
2024-02-15T14:28:44.907022471Z Documentation: http://aka.ms/webapp-linux
2024-02-15T14:28:44.907025671Z Python 3.7.17
2024-02-15T14:28:44.907028771Z Note: Any data outside '/home' is not persisted
2024-02-15T14:28:47.919246257Z Starting OpenBSD Secure Shell server: sshd.
2024-02-15T14:28:48.126441484Z Site's appCommandLine: gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:APP
2024-02-15T14:28:48.126477484Z Launching oryx with: create-script -appPath /home/site/wwwroot -output /opt/startup/startup.sh -virtualEnvName antenv -defaultApp /opt/defaultsite -userStartupCommand 'gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:APP'
2024-02-15T14:28:48.187623605Z Found build manifest file at '/home/site/wwwroot/oryx-manifest.toml'. Deserializing it...
2024-02-15T14:28:48.187668106Z Build Operation ID: 1014dbc4d99e9853
2024-02-15T14:28:48.197276572Z Output is compressed. Extracting it...
2024-02-15T14:28:48.205194026Z Extracting '/home/site/wwwroot/output.tar.gz' to directory '/tmp/8dc2e31979c41aa'...
2024-02-15T14:28:48.197713275Z Oryx Version: 0.2.20230707.1, Commit: 0bd28e69919b5e8beba451e8677e3345f0be8361, ReleaseTagName: 20230707.1
2024-02-15T14:28:50.351728409Z App path is set to '/tmp/8dc2e31979c41aa'
2024-02-15T14:28:51.165217213Z Writing output script to '/opt/startup/startup.sh'
2024-02-15T14:28:51.425979509Z Using packages from virtual environment antenv located at /tmp/8dc2e31979c41aa/antenv.
2024-02-15T14:28:51.449039868Z Updated PYTHONPATH to '/opt/startup/app_logs:/tmp/8dc2e31979c41aa/antenv/lib/python3.7/site-packages'
2024-02-15T14:28:55.296754676Z 
2024-02-15T14:28:55.296796276Z Error: class uri 'aiohttp.worker.GunicornWebWorker' invalid or not found: 
2024-02-15T14:28:55.296803276Z 
2024-02-15T14:28:55.296807276Z [Traceback (most recent call last):
2024-02-15T14:28:55.296811176Z   File "/opt/python/3.7.17/lib/python3.7/site-packages/gunicorn/util.py", line 99, in load_class
2024-02-15T14:28:55.296815276Z     mod = importlib.import_module('.'.join(components))
2024-02-15T14:28:55.296819076Z   File "/opt/python/3.7.17/lib/python3.7/importlib/__init__.py", line 127, in import_module
2024-02-15T14:28:55.296822976Z     return _bootstrap._gcd_import(name[level:], package, level)
2024-02-15T14:28:55.296826776Z   File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
2024-02-15T14:28:55.296840176Z   File "<frozen importlib._bootstrap>", line 983, in _find_and_load
2024-02-15T14:28:55.296844176Z   File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
2024-02-15T14:28:55.296847976Z   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
2024-02-15T14:28:55.296851776Z   File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
2024-02-15T14:28:55.296859076Z   File "<frozen importlib._bootstrap>", line 983, in _find_and_load
2024-02-15T14:28:55.296862676Z   File "<frozen importlib._bootstrap>", line 965, in _find_and_load_unlocked
2024-02-15T14:28:55.296866477Z ModuleNotFoundError: No module named 'aiohttp'
2024-02-15T14:28:55.296869977Z ]

I have found this SO but it did not solve my problem.

Here's my requirements.txt:

botbuilder_schema==4.13.0
gunicorn==20.1.0
aiohttp==3.6.3
botbuilder-integration-aiohttp==4.13.0
botbuilder-ai==4.13.0
botbuilder==0.0.1
botbuilder-core==4.13.0
botbuilder-dialogs==4.13.0

Here's my .deployment:

[config]
SCM_DO_BUILD_DURING_DEPLOYMENT = true

Here are the files inside of my root folder:

And here's the command I am using to deploy the bot: az webapp deployment source config-zip --resource-group "resource_name" --name "service_name" --src "echo-bot.zip"

Please help!


Solution

  • Follow below steps to deploy echo bot application.

    I have created a python echo bot project with Python 3.9 version and able to run locally.

    py -m venv env
    .\env\Scripts\activate
    

    Added below packages in requirements.txt

    botbuilder-integration-aiohttp>=4.14.0
    aiohttp
    botbuilder-core
    botbuilder-schema
    
    pip install -r requirements.txt
    

    Local Response:

    enter image description here

    import sys
    import traceback
    from datetime import datetime
    from aiohttp import web
    from aiohttp.web import Request, Response, json_response
    from botbuilder.core import (BotFrameworkAdapter, BotFrameworkAdapterSettings,
                                 TurnContext)
    from botbuilder.core.integration import aiohttp_error_middleware
    from botbuilder.schema import Activity, ActivityTypes
    
    from bot import MyBot
    from config import DefaultConfig
    
    CONFIG = DefaultConfig()
    
    SETTINGS = BotFrameworkAdapterSettings(CONFIG.APP_ID, CONFIG.APP_PASSWORD)
    ADAPTER = BotFrameworkAdapter(SETTINGS)
    
    async def on_error(context: TurnContext, error: Exception):
    
        print(f"\n [on_turn_error] unhandled error: {error}", file=sys.stderr)
        traceback.print_exc()
    
        await context.send_activity("The bot encountered an error or bug.")
        await context.send_activity(
            "To continue to run this bot, please fix the bot source code."
        )
    
        if context.activity.channel_id == "emulator":
    
            trace_activity = Activity(
                label="TurnError",
                name="on_turn_error Trace",
                timestamp=datetime.utcnow(),
                type=ActivityTypes.trace,
                value=f"{error}",
                value_type="https://www.botframework.com/schemas/error",
            )
            await context.send_activity(trace_activity)
    
    ADAPTER.on_turn_error = on_error
    
    # Create the Bot
    BOT = MyBot()
    
    # Listen for incoming requests on /api/messages
    async def messages(req: Request) -> Response:
        # Main bot message handler.
        if "application/json" in req.headers["Content-Type"]:
            body = await req.json()
        else:
            return Response(status=415)
    
        activity = Activity().deserialize(body)
        auth_header = req.headers["Authorization"] if "Authorization" in req.headers else ""
    
        response = await ADAPTER.process_activity(activity, auth_header, BOT.on_turn)
        if response:
            return json_response(data=response.body, status=response.status)
        return Response(status=201)
        
    # enclosing the below code with init_func()
    
    def init_func(argv):
        APP = web.Application(middlewares=[aiohttp_error_middleware])
        APP.router.add_post("/api/messages", messages)
        return APP
    if __name__ == "__main__":
        APP = init_func(None)
    
        try:
            web.run_app(APP, host="0.0.0.0", port=CONFIG.PORT)
        except Exception as error:
            raise error
    
    class DefaultConfig:
        """ Bot Configuration """
        PORT = 3978
        APP_ID = os.environ.get("MicrosoftAppId", "a573434f-3b7b-4e52-919a-c574d56965b5")
        APP_PASSWORD = os.environ.get("MicrosoftAppPassword", "mWk8Q~.6uGbHAvNzBlg3T6kikKfPUCaC7HV~sdpW")
    

    enter image description here

    python3 -m aiohttp.web -H 0.0.0.0 -P 8000 app:init_func
    

    enter image description here

    Test the Bot:

    enter image description here