"ImportError: cannot import name 'Sequence' from 'collections'" - Azure Linux web app with Python and Django

213 views Asked by At

I have a Django app that I am deploying as a Azure linux web app. It has been running fine for months but now on startup after deployment via AzDO CI/CD pipeline it errors with from collections import Sequence at line 10 when loading pathlib.py from the MS version in the docker container. The official version of pathlib.py (https://github.com/python/cpython/blob/3.12/Lib/pathlib.py) reads from _collections_abc import Sequence See docs at https://docs.python.org/3/library/pathlib.html This is a known problem and is resolved by moving from the MS version to the later official version. The issue is that this problem is in the MS distro and not in my code or even the version of the library that gets installed with pip. Even if you change it, any deployment over-writes the correct version with the version in the MS distro.

The app works fine locally with the official pathlib.py and previously worked OK on Azure. It looks like a regression error with the library being used. I have tried editing the Azure version of pathlib.py but it gets over-written on every [container] restart or redeployment.

How can I change the version of pathlib.py being used by Azure or otherwise work-around this please?

1

There are 1 answers

0
SiddheshDesai On
  • Make sure you are using the correct version of pathlib.py in your project directory and load it in your system.

  • You can create a docker image and deploy your Dockerized Web App in Azure.

  • During the initialization phase of your application, such as in Django's settings.py file, you can modify the behavior of pathlib after importing it by adjusting the Sequence class to use the correct one from _collections_abc. This approach might require making alterations to the internal functionality of pathlib, commonly referred to as monkey-patching, although it's not an ideal solution, it could function as a temporary fix.

My Folder Structure:-

enter image description here

pathlib.py:-

# custom_libs/pathlib.py

import pathlib
from collections.abc import Sequence as CollectionsSequence

# Override Sequence in pathlib to use the correct CollectionsSequence
pathlib.Sequence = CollectionsSequence

My settings.py:-

import os
from pathlib import Path
import sys
import pathlib
from collections.abc import Sequence as CollectionsSequence


# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
sys.path.insert(0, os.path.join(BASE_DIR, 'custom_libs'))
pathlib.Sequence = CollectionsSequence

My Azure DevOps yaml pipeline:-

trigger:
- main

variables:
  
  azureServiceConnectionId: '68cxxxxa288-313d82b922f2'


  webAppName: 'silicondjangowebapp'

  
  vmImageName: 'ubuntu-latest'

  
  environmentName: 'silicondjangowebapp'

  
  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 : silicondjangowebapp'
            inputs:
              azureSubscription: $(azureServiceConnectionId)
              appName: $(webAppName)
              package: $(Pipeline.Workspace)/drop/$(Build.BuildId).zip

Output:-

enter image description here