Search code examples
python-3.xdjangodocker-composedockerfile

ImportError: cannot import name 'python_2_unicode_compatible' from 'django.utils.encoding' in building docker


I'm new to learning docker and django. I've tried to dockerize an existing django project for adding MySQL database and command "runserver". After changing requirements.txt for dependecy conflict, my "runserver" container is running, but I can't see the app on my local. Here is my traceback:

`runserver-1       | Exception in thread django-main-thread:
runserver-1       | Traceback (most recent call last):
runserver-1       |   File "/usr/local/lib/python3.11/threading.py", line 1045, in _bootstrap_inner
runserver-1       |     self.run()
runserver-1       |   File "/usr/local/lib/python3.11/site-packages/sentry_sdk/integrations/threading.py", line 69, in run
runserver-1       |     reraise(*_capture_exception())
runserver-1       |   File "/usr/local/lib/python3.11/site-packages/sentry_sdk/_compat.py", line 57, in reraise
runserver-1       |     raise value
runserver-1       |   File "/usr/local/lib/python3.11/site-packages/sentry_sdk/integrations/threading.py", line 67, in run
runserver-1       |     return old_run_func(self, *a, **kw)
runserver-1       |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
runserver-1       |   File "/usr/local/lib/python3.11/threading.py", line 982, in run
runserver-1       |     self._target(*self._args, **self._kwargs)
runserver-1       |   File "/usr/local/lib/python3.11/site-packages/django/utils/autoreload.py", line 64, in wrapper
runserver-1       |     fn(*args, **kwargs)
runserver-1       |   File "/usr/local/lib/python3.11/site-packages/django/core/management/commands/runserver.py", line 110, in inner_run
runserver-1       |     autoreload.raise_last_exception()
runserver-1       |   File "/usr/local/lib/python3.11/site-packages/django/utils/autoreload.py", line 87, in raise_last_exception
runserver-1       |     raise _exception[1]
runserver-1       |   File "/usr/local/lib/python3.11/site-packages/django/core/management/__init__.py", line 375, in execute
runserver-1       |     autoreload.check_errors(django.setup)()
runserver-1       |   File "/usr/local/lib/python3.11/site-packages/django/utils/autoreload.py", line 64, in wrapper
runserver-1       |     fn(*args, **kwargs)
runserver-1       |   File "/usr/local/lib/python3.11/site-packages/django/__init__.py", line 24, in setup
runserver-1       |     apps.populate(settings.INSTALLED_APPS)
runserver-1       |   File "/usr/local/lib/python3.11/site-packages/django/apps/registry.py", line 114, in populate
runserver-1       |     app_config.import_models()
runserver-1       |   File "/usr/local/lib/python3.11/site-packages/django/apps/config.py", line 301, in import_models
runserver-1       |     self.models_module = import_module(models_module_name)
runserver-1       |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
runserver-1       |   File "/usr/local/lib/python3.11/importlib/__init__.py", line 126, in import_module
runserver-1       |     return _bootstrap._gcd_import(name[level:], package, level)
runserver-1       |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
runserver-1       |   File "<frozen importlib._bootstrap>", line 1204, in _gcd_import
runserver-1       |   File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
runserver-1       |   File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
runserver-1       |   File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
runserver-1       |   File "<frozen importlib._bootstrap_external>", line 940, in exec_module
runserver-1       |   File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
runserver-1       |   File "/usr/local/lib/python3.11/site-packages/captcha/models.py", line 4, in <module>
runserver-1       |     from django.utils.encoding import python_2_unicode_compatible
runserver-1       | ImportError: cannot import name 'python_2_unicode_compatible' from 'django.utils.encoding' (/usr/local/lib/python3.11/site-packages/django/utils/encoding.py)`

Here are my Dockerfile and docker-compose.yml:

FROM python:3.11

WORKDIR /app

COPY requirements.txt /app

RUN pip install -r requirements.txt 

COPY . /app

EXPOSE 8000

CMD ["python3", "manage.py", "runserver", "0.0.0.0:8000"]

services:
  db:
    container_name: ***
    image: mysql:latest
    healthcheck:
      test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ]
      interval: 10s
      timeout: 3s
      retries: 3
    restart: always
    environment:
      MYSQL_DATABASE: ***
      MYSQL_USER: ***
      MYSQL_PASSWORD: ***
      MYSQL_ROOT_PASSWORD: ***
    ports:
      - "3306:3306"

  runserver:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    working_dir: /app
    volumes:
      - .:/app
    ports:
      - "8000:8000"
    depends_on:
      - db
    environment:
      DB_HOST: db
      DB_NAME: ***
      DB_USER: ***
      DB_PASSWORD: ***

Solution

  • Following your error traceback, I think you are using Python 3:11, and the importError occurs at the folder root of your project, site-packages/django/utils/encoding.py. The cause of this error is the fact that the current Django version is not compatible with the existing Django project you are trying to dockerize which uses version 2 series of Django. These two can't work, thus the result of the error.

    You can solve this issue by either:

    Consider downgrading your Django version on your requirements.txt to Django 2.2 which utilizes the Python 2 compatibility APIs by running your pip command; pip install django==2.2.

    OR

    You can customize your code by targeting the exact path to the error above by importing the code below at the upper level of the module, encoding.py. For this code below to work, make sure that six python package is installed, and if you haven't, kindly install it; pip install six, and when you are done, run your pip freeze > requirements.txt.

    
     from six import python_2_unicode_compatible