Docker部署Django+DRF项目遇PyO3模块初始化错误求助
问题:Docker化Django+DRF项目启动时出现PyO3初始化错误
我正在开发一个包含DRF的Docker化Django项目,此前运行一切正常,但今日执行docker-compose up -d启动容器后,日志中突然出现ImportError: PyO3 modules may only be initialized once per interpreter process错误,完全不清楚原因。
相关错误日志
patients | [uWSGI] getting INI configuration from /patients/src/_settings/local-test/uwsgi.ini patients | [uwsgi-static] added mapping for /static/ => /static/ patients | *** Starting uWSGI 2.0.21 (64bit) on [Fri Jun 2 13:59:34 2023] *** patients | compiled with version: 10.2.1 20210110 on 02 June 2023 10:11:18 patients | os: Linux-5.19.0-42-generic #43~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Apr 21 16:51:08 UTC 2 patients | nodename: 9be86066078d patients | machine: x86_64 patients | clock source: unix patients | pcre jit disabled patients | detected number of CPU cores: 8 patients | current working directory: /patients/src patients | detected binary path: /usr/local/bin/uwsgi patients | uWSGI running as root, you can use --uid/--gid/--chroot options patients | setgid() to 33 patients | *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** patients | chdir() to /patients/src patients | your memory page size is 4096 bytes patients | detected max file descriptor number: 1048576 patients | building mime-types dictionary from file /etc/mime.types...1476 entry found patients | lock engine: pthread robust mutexes patients | thunder lock: disabled (you can enable it with --thunder-lock) patients | uwsgi socket 0 bound to TCP address :8080 fd 3 patients | uWSGI running as root, you can use --uid/--gid/--chroot options patients | setgid() to 33 patients | *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** patients | Python version: 3.9.16 (main, May 23 2023, 14:17:54) [GCC 10.2.1 20210110] patients | Python main interpreter initialized at 0x5640005ce9b0 patients | uWSGI running as root, you can use --uid/--gid/--chroot options patients | setgid() to 33 patients | *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** patients | python threads support enabled patients | your server socket listen backlog is limited to 100 connections patients | your mercy for graceful operations on workers is 60 seconds patients | mapped 618762 bytes (604 KB) for 4 cores patients | *** Operational MODE: preforking+threaded *** patients | WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x5640005ce9b0 pid: 1 (default app) patients | mounting /patients/src/patients/wsgi.py on /patients patients | Traceback (most recent call last): patients | File "/patients/src/patients/wsgi.py", line 16, in <module> patients | application = get_wsgi_application() patients | File "/usr/local/lib/python3.9/site-packages/django/core/wsgi.py", line 12, in get_wsgi_application patients | django.setup(set_prefix=False) patients | File "/usr/local/lib/python3.9/site-packages/django/__init__.py", line 24, in setup patients | apps.populate(settings.INSTALLED_APPS) patients | File "/usr/local/lib/python3.9/site-packages/django/apps/registry.py", line 114, in populate patients | app_config.import_models() patients | File "/usr/local/lib/python3.9/site-packages/django/apps/config.py", line 301, in import_models patients | self.models_module = import_module(models_module_name) patients | File "/usr/local/lib/python3.9/importlib/__init__.py", line 127, in import_module patients | return _bootstrap._gcd_import(name[level:], package, level) patients | File "<frozen importlib._bootstrap>", line 1030, in _gcd_import patients | File "<frozen importlib._bootstrap>", line 1007, in _find_and_load patients | File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked patients | File "<frozen importlib._bootstrap>", line 680, in _load_unlocked patients | File "<frozen importlib._bootstrap_external>", line 850, in exec_module patients | File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed patients | File "/patients/src/./patient/models.py", line 3, in <module> patients | from django_cryptography.fields import encrypt patients | File "/usr/local/lib/python3.9/site-packages/django_cryptography/fields.py", line 9, in <module> patients | from django_cryptography.core.signing import SignatureExpired patients | File "/usr/local/lib/python3.9/site-packages/django_cryptography/core/signing.py", line 10, in <module> patients | from cryptography.exceptions import InvalidSignature patients | File "/usr/local/lib/python3.9/site-packages/cryptography/exceptions.py", line 9, in <module> patients | from cryptography.hazmat.bindings._rust import exceptions as rust_exceptions patients | ImportError: PyO3 modules may only be initialized once per interpreter process
docker-compose.yml配置
version: '3' services: patients: container_name: patients image: patients:latest restart: always volumes: - ./:/patients/ env_file: - patients.env command: ["uwsgi", "--ini", "/patients/src/_settings/local-test/uwsgi.ini"] ports: - 8003:8080 build: ./
uwsgi.ini配置
[uwsgi] http-socket = :8080 chdir =/patients/src master = 1 processes = 2 threads = 2 static-map = /static/=/static/ mount =/patients=/patients/src/patients/wsgi.py manage-script-name = true buffer-size = 65535 module=patients.wsgi vacuum = True gid = www-data env = PYTHONDONTWRITEBYTECODE=1
排查与解决方案
1. 调整uWSGI应用加载模式
PyO3模块要求每个Python解释器进程只能初始化一次,而uWSGI默认预加载模式会在master进程初始化应用后,将内存复制给worker进程,导致PyO3模块被重复初始化。
修改uwsgi.ini,添加以下配置:
lazy-apps = true
该选项会让每个worker进程单独初始化应用,避免master进程预加载带来的重复初始化问题。
2. 移除重复的应用挂载配置
你的uwsgi.ini中同时配置了mount和module,会导致应用被初始化两次,触发PyO3错误。建议保留其中一种配置:
- 若不需要挂载到子路径,直接删除
mount和manage-script-name两行,仅保留module=patients.wsgi; - 若需要挂载到
/patients路径,删除module=patients.wsgi,确保只通过mount初始化一次应用。
3. 锁定依赖版本
可能是cryptography或django-cryptography依赖更新后引入了PyO3相关变化,尝试将这些依赖锁定到之前正常运行的版本。比如在requirements.txt中添加:
cryptography==39.0.1 django-cryptography==1.1
根据自身环境调整具体版本号。
4. 清理Docker缓存重新构建镜像
Docker缓存的旧依赖或编译文件可能导致问题,执行以下命令重新构建镜像:
docker-compose build --no-cache docker-compose up -d
内容的提问来源于stack exchange,提问作者Muhammad Safwan
相关产品推荐
相关产品推荐

