gevent==22.10.2
gunicorn==20.1.0
django==3.2.19
"""Gunicorn config file"""
# import os
from core.utilities.env import get_env_value
from core.config.logging import DJANGO_DIR_LOG
# Django WSGI application path in pattern MODULE_NAME:VARIABLE_NAME
wsgi_app = 'core.wsgi:application' # 'core.asgi:application' need FastAPI
# The granularity of Error log outputs
loglevel = 'debug'
# The number of worker processes for handling requests (at the moment we don't use more than 2 workers, because the analytical process (celery container) needs so many resources, to be tested)
workers = 2 # os.cpu_count() * 2 + 1
# Use Uvicorn worker for async mode
# worker_class = 'uvicorn.workers.UvicornWorker' need FastAPI
worker_class = 'gevent'
preload_app = True
# The maximum number of requests a worker can handle before being restarted
max_requests = 1000
max_requests_jitter = 50
# The number of seconds to wait for requests to complete
timeout = 300
# The socket to bind
bind = '0.0.0.0:7000'
# accesslog = DJANGO_DIR_LOG + '/gunicorn/access.log'
errorlog = DJANGO_DIR_LOG + '/gunicorn/error.log'
# Redirect stdout/stderr to log file
capture_output = False
# PID file so you can easily fetch process ID
pidfile = '/run/gunicorn/gunicorn.pid'
# Daemonize the Gunicorn process (detach & enter background)
daemon = False
# Set user and group for running Gunicorn
user = 'mambauser'
chdir = '/code/Analyser'
I use django with gunicorn, as long as I use the default worker_class everything is ok, fine, even if the suggested workers (os.cpu_count() * 2 + 1) consume too much ram.
I wanted to use Gevent to have I/O optimizations, but when I use it it gives me the error:
File "/opt/conda/lib/python3.9/site-
packages/django/db/models/sql/compiler.py", line 1414, in execute_sql
with self.connection.cursor() as cursor:
File "/opt/conda/lib/python3.9/site-packages/django/utils/asyncio.py", line 31, in inner
raise SynchronousOnlyOperation(message)
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.
I have this problem with sync & async views, in my wsgi.py i put
from pycogreen.gevent import patch_psycopg
from gevent.monkey import patch_all
patch_all()
patch_psycopg()
But nothig change
This is my async view:
class ListTests(APIView):
@async_to_sync
async def get(self, request, *args, **kwargs):
test_task = asyncio.create_task(test_repository.count_expired_async())
................
test_count = await test_task
............
TraceBack
2023-05-25 13:38:42.680 | ERROR | .views:get:87 - unhandled exception in get tests information
Traceback (most recent call last):
File "/opt/conda/lib/python3.9/site-packages/asgiref/sync.py", line 306, in main_wrap
result = await self.awaitable(*args, **kwargs)
│ │ │ └ {}
│ │ └ (<views.LisTests object at 0x7f6508874df0>, <rest_framework.request.Request: GET '...
│ └ <function ListBadges.get at 0x7f6508cbb670>
└ <asgiref.sync.AsyncToSync object at 0x7f6508c371c0>
> File "/views.py", line 64, in get
test_count = await test_task
└ <coroutine object asyncio.create_task at 0x7f6508848d40>
File "/views.py", line 47, in asyncio.create_task
return await task
└ <Task finished name='Task-5' coro=<SyncToAsync.__call__() done, defined at /opt/conda/lib/python3.9/site-packages/asgiref/syn...
File "/opt/conda/lib/python3.9/asyncio/futures.py", line 284, in __await__
yield self # This tells Task to wait for completion.
└ <Task finished name='Task-5' coro=<SyncToAsync.__call__() done, defined at /opt/conda/lib/python3.9/site-packages/asgiref/syn...
File "/opt/conda/lib/python3.9/asyncio/tasks.py", line 328, in __wakeup
future.result()
│ └ <function Future.result at 0x7f652f3ee3a0>
└ <Task finished name='Task-5' coro=<SyncToAsync.__call__() done, defined at /opt/conda/lib/python3.9/site-packages/asgiref/syn...
File "/opt/conda/lib/python3.9/asyncio/futures.py", line 201, in result
raise self._exception
│ └ SynchronousOnlyOperation('You cannot call this from an async context - use a thread or sync_to_async.')
└ <Task finished name='Task-5' coro=<SyncToAsync.__call__() done, defined at /opt/conda/lib/python3.9/site-packages/asgiref/syn...
File "/opt/conda/lib/python3.9/asyncio/tasks.py", line 258, in __step
result = coro.throw(exc)
│ └ <method 'throw' of 'coroutine' objects>
└ <coroutine object SyncToAsync.__call__ at 0x7f6508848cc0>
File "/opt/conda/lib/python3.9/site-packages/asgiref/sync.py", line 448, in __call__
ret = await asyncio.wait_for(future, timeout=None)
│ │ └ <Future finished exception=SynchronousOnlyOperation('You cannot call this from an async context - use a thread or sync_to_asy...
│ └ <function wait_for at 0x7f652f38aa60>
└ <module 'asyncio' from '/opt/conda/lib/python3.9/asyncio/__init__.py'>
File "/opt/conda/lib/python3.9/asyncio/tasks.py", line 442, in wait_for
return await fut
└ <Future finished exception=SynchronousOnlyOperation('You cannot call this from an async context - use a thread or sync_to_asy...
File "/opt/conda/lib/python3.9/asyncio/futures.py", line 284, in __await__
yield self # This tells Task to wait for completion.
└ <Future finished exception=SynchronousOnlyOperation('You cannot call this from an async context - use a thread or sync_to_asy...
File "/opt/conda/lib/python3.9/asyncio/tasks.py", line 328, in __wakeup
future.result()
│ └ <function Future.result at 0x7f652f3ee3a0>
└ <Future finished exception=SynchronousOnlyOperation('You cannot call this from an async context - use a thread or sync_to_asy...
File "/opt/conda/lib/python3.9/asyncio/futures.py", line 201, in result
raise self._exception
│ └ SynchronousOnlyOperation('You cannot call this from an async context - use a thread or sync_to_async.')
└ <Future finished exception=SynchronousOnlyOperation('You cannot call this from an async context - use a thread or sync_to_asy...
File "/opt/conda/lib/python3.9/site-packages/asgiref/current_thread_executor.py", line 22, in run
result = self.fn(*self.args, **self.kwargs)
│ │ └ None
│ └ None
└ None
File "/opt/conda/lib/python3.9/site-packages/asgiref/sync.py", line 490, in thread_handler
return func(*args, **kwargs)
│ │ └ {}
│ └ (functools.partial(<function UsageBasedMaintenanceRepository.count_expired at 0x7f652be1f310>, <main.services.repository.usag...
└ <built-in method run of Context object at 0x7f650888b780>
File "/repository/test_repository.py", line 59, in count_expired
return len(self.get_can_result())
│ └ <function TestRepository.get_can_result at 0x7f652be1f280>
└ .repository.test_repository.TestRepository object at 0x7f652be498e0>
File "/repository/test_repository.py", line 50, in get_can_result
for test in self.get_started(test_n):
│ │ └ None
│ └ <function TestRepository.get_started at 0x7f652be1f160>
└ <repository.test_repository.TestRepositoryobject at 0x7f652be498e0>
File "/opt/conda/lib/python3.9/site-packages/django/db/models/query.py", line 280, in __iter__
self._fetch_all()
│ └ <function QuerySet._fetch_all at 0x7f652ea4c3a0>
└ <unprintable QuerySet object>
File "/opt/conda/lib/python3.9/site-packages/django/db/models/query.py", line 1324, in _fetch_all
self._result_cache = list(self._iterable_class(self))
│ │ │ │ └ <unprintable QuerySet object>
│ │ │ └ <class 'django.db.models.query.ModelIterable'>
│ │ └ <unprintable QuerySet object>
│ └ None
└ <unprintable QuerySet object>
File "/opt/conda/lib/python3.9/site-packages/django/db/models/query.py", line 51, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
│ │ │ │ │ └ 100
│ │ │ │ └ <django.db.models.query.ModelIterable object at 0x7f6508870880>
│ │ │ └ False
│ │ └ <django.db.models.query.ModelIterable object at 0x7f6508870880>
│ └ <function SQLCompiler.execute_sql at 0x7f652756e3a0>
└ <django.db.models.sql.compiler.SQLCompiler object at 0x7f65088701f0>
File "/opt/conda/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1173, in execute_sql
cursor = self.connection.cursor()
│ │ └ <function BaseDatabaseWrapper.cursor at 0x7f652d4c94c0>
│ └ <timescale.db.backends.postgresql.base.DatabaseWrapper object at 0x7f65088dc700>
└ <django.db.models.sql.compiler.SQLCompiler object at 0x7f65088701f0>
File "/opt/conda/lib/python3.9/site-packages/django/utils/asyncio.py", line 31, in inner
raise SynchronousOnlyOperation(message)
│ └ 'You cannot call this from an async context - use a thread or sync_to_async.'
└ <class 'django.core.exceptions.SynchronousOnlyOperation'>
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.