Forums

DJANGO Q - MULTIPROCESSING

Hello, im trying to run backround tasks in django

Can i use django q in my views.py to create a task: async_task('math.copysign', 2, -2) And then on an always on task, running on manangement/commands, process the tasks?

I already read this article: https://blog.pythonanywhere.com/198/

If you use the Django ORM for your broker, it should be fine.

I’m trying to do the same, how did you set this up? What does the always-on file look like exactly? I’m confused about what the broker is vs the always-on task.

@damanc7 -- have a look at this blog post. If I understand correctly, in this particular scenario, the Always-on task would be a Django management command.

@pafk This is the relevant information I see in the blog post

"All right! Whenever someone hits our main page, we will store the request information in the database. On this stage we can move to the processing part. In our simplistic example we need to do only two things: check for a pending request in the database and perform the processing if needed:"

I understand it in theory but this Flask example doesn't translate to Django and Django-Q. From @glenn it looks like you should use the ORM broker but what exactly is in the always-on task and how do the two communicate? This is the setup I have. My Always-On task says seems to be perpetually "starting" and my server log says "Enqueued".

Always-On Task Log

2022-03-14 16:03:40 - Task preparing to start

Server Log

2022-03-14 08:42:41 announcing my loyalty to the Emperor...
2022-03-14 08:43:35 08:43:35 [Q] INFO Enqueued 3
2022-03-14 08:47:33 08:47:33 [Q] INFO Enqueued 4
2022-03-14 09:13:23 09:13:23 [Q] INFO Enqueued 5

settings.py

Q_CLUSTER = {
'name': 'DjangORM',
'workers': 4,
'timeout': 90,
'retry': 120,
'queue_limit': 50,
'bulk': 10,
'orm': 'default'

}

services.py

import time

def get_data(url):
    time.sleep(10)
    return 'THIS IS MY SERVICES.PY COMPLETE'

def get_data_hook(task):
    print(task.result)

views.py

from django_q.tasks import async_task
from django.http import HttpResponse

def async_test(request):
    async_task("mysite.mysite.services.get_data",
            "https://google.com",
            hook = "mysite.mysite.services.get_data_hook")
    html = "<html><body>Submitted</body></html>"
    return HttpResponse(html)

Always-On Task

python3.8 -u /home/damanc7/mysite/mysite/services.py

Your services.py does nothing. It just defines 2 functions. So your always on task is basically starting it, having it exit and then starting it again. You will need to actually do something in the always on task beyond defining some functions.

I've altered the always-on code with a print statement so now it is continually running which is great but I'm still not seeing the functions in the always-on task get triggered with django-q.

services.py

import time

def get_data(text):
    time.sleep(10)
    return 'THIS IS SERVICES.PY COMPLETE' + text

def get_data_hook(task):
    print(task.result)

print('Services.py Always-On Task is Running')

views.py

from django_q.tasks import async_task
from django.http import HttpResponse

def async_test(request):
    async_task("mysite.mysite.services.get_data",
            "FROM VIEWS.PY",
            hook = "mysite.mysite.services.get_data_hook")
    html = "<html><body>Submitted</body></html>"
    return HttpResponse(html)

Always-On Task Log

Mar 17 17:19:13 Services.py Always-On Task is Running
Mar 17 17:19:56 Services.py Always-On Task is Running
Mar 17 17:21:32 Services.py Always-On Task is Running

Have you checked that the tasks you are queuing are actually being added to your database?

no... My understanding was that it goes within djangos's database system? I'm not sure. I see this on the log.

2022-03-17 10:19:48 10:19:48 [Q] INFO Enqueued 6

https://django-q.readthedocs.io/en/latest/configure.html#orm I added this example to my setting.py file. I cannot find any tutorials for django, django-q, pythonanywhere integration so your help is greatly appreciated!

Make sure that you're running the Cluster correctly, so that it can pick up the tasks: https://django-q.readthedocs.io/en/latest/cluster.html

Okay, I finally got it a simple async going with django-q. I had failed queues stuck retrying over and over so I had to go into the django admin panel and manually delete them. For anyone else that finds this thread:

settings.py

Q_CLUSTER = {
'name': 'DjangORM',
'workers': 1,
'timeout': 90,
'retry': 120,
'queue_limit': 50,
'bulk': 10,
'orm': 'default',
'ack_failures': True,
'max_attempts': 1,
'attempt_count': 1,}

views.py

from django.http import JsonResponse
from django_q.tasks import async_task

def index(request):
    json_payload = {"message": "hello world!"}
    # enqueue the task
    async_task("polls.services.sleep_and_print", 10)
    return JsonResponse(json_payload)

/mysite/polls/services.py

from time import sleep
def sleep_and_print(secs):
    sleep(secs)
    print("Task ran!")

print('always-on task is on')

Always on Task (this takes awhile to start)

/home/damanc7/.virtualenvs/djangoenv/bin/python3.7  /home/damanc7/mysite/polls/services.py

Run the webapp and start a bash console with:

Bash in virtual environment

python manage.py qcluster

Make a call to your view by going to the website. In my case it was http://mysite/polls/

If you see this in bash:

always-on task is on
Task ran!

It was successful!

Thanks for sharing that!

I've found that running qcluster is taking up CPU usage at a rate of 1:1 even when not running tasks through my django website. Between this and the always-on task required, it really taxes the CPU usage even while waiting. Is there any way to cut my CPU usage down to only when I'm actually running tasks?

python manage.py qcluster

I think the answer here would be similar to that in another thread where you asked similar question.

Thanks for your suggestions and I understand that the sleep function can cut down on CPU usage. However, this is for a website that runs 24/7. I have purchased always-on tasks to support the Django website but I’m trying to avoid paying for each second of CPU time while the django-q cluster is just sitting there waiting for tasks.

Is there a way to not be charged for CPU time while waiting for a website task but still be ready to take on a task at anytime?

I know CPU time is only charged for consoles and always-on tasks. Since this is directly related to my webapp, is there a way to route it that way?

You are charged CPU for task only when that tasks uses CPU. Most of the tasks deployed on PythonAnywhere are directly related to some web app.

You are charged CPU for task only when that tasks uses CPU.

This is the issue. According to PA, I am using CPU at a ratio of 1 CPU second to 1 clock second simply waiting for tasks from my webapp.

When deciding if I should use PythonAnywhere I researched the help documentation which said asynchronous tasks can be done in Django through django-q via an always-on task. It did not say that to do this you would be using your CPU time at full capacity for simply waiting for a task.

We charge CPU seconds only when your code is doing something. Active checking if there is something to do is doing.

Thank you for the code and it was very helpful. I have successfully used python manage.py qcluster for my application. I've found on other sites that recommend adding it to the Procfile. Could you please guide me on how to use qcluster in a production environment on PythonAnywhere?"

https://django-q.readthedocs.io/en/latest/cluster.html#using-a-procfile

A procfile is something specific to Heroku -- the equivalent on PythonAnywhere would be to set up the management command as an always-on task.

Thank you for your reply. I apologize for not reading the previous message carefully.

I set a task on Always on Task just like this /home/damanc7/.virtualenvs/djangoenv/bin/python3.7 /home/damanc7/mysite/polls/services.py

Open the terminal in a virtual environment. Run the command 'python manage.py qcluster'. My question is, can I close the browser while these commands are running? Will they continue to run even if the browser is closed?

Yeah they'll keep running

Hello,

Django Q has been running for about a week using the "Always-on tasks" feature on PythonAnywhere, and it's been working just fine. However, I've noticed that my Django Q tasks suddenly stopped unexpectedly. Restarting the task fixed the problem and everything returned to normal, but I'm concerned about when this might happen again.

I'm curious to know if anyone here is using Django Q in a production environment? Is it reliable for such use? And if so, are there any monitoring tools or practices you use to ensure its continuous operation?

Any advice or experiences shared would be greatly appreciated. Thank you.

How it stopped? Do you have a traceback? If it was Always-on tasks it should have been restarted. Did it happen?

Hello,

Thank you for your response.

As for how it stopped, I'm not exactly sure. That's what I'm trying to determine. Regarding the traceback, I'm not certain how to check it on PythonAnywhere. Would you be able to guide me on how to retrieve it? I haven't set up any custom logging for Django Q. Do you think it's essential to implement one to track down issues like this? I understand that it may not necessarily be an error in my code, but I'm also considering the possibility of an issue on the side of the "Always-on tasks" feature. Any advice or further insight you could provide would be greatly appreciated. Thank you.

There are logs. One of the buttons next the task definition leads to them. Are you running qcluster management command as Alwayson task?

Are you running qcluster management command as Alwayson task? > yes

Currently, I can only view the basic log through the "view task log". Do I need to write code to output the error log here? Would wrapping it with a try-except clause be appropriate?

I've noticed that after running python manage.py qcluster multiple times, it seems that multiple qcluster processes are running in the background. The CPU usage used to be around 30%, but recently it has surged past 70%. How can I confirm the number of active qcluster processes? Moreover, how can I properly stop them? In its current state, it doesn't seem feasible for production mode.

If you want something to be logged in the task log, you will need to provide code that generates those logs.

If you run a command multiple times, it will be running multiple times and consume CPU for each of the processes that are running. You can see running processes using the "Fetch process list" button on the Consoles and Tasks pages (they are 2 different lists)

QCluster Processes: I've only executed the python manage.py qcluster command once, but I notice that there are always 5 processes running. Is this expected behavior?

Fetch process list

Processes Falling Over Time: After running tasks for about 3 days, they consistently fail. I've wrapped my code with a try-except block, so I believe it isn't an issue with my program. However, I received an email from PythonAnywhere stating, "You've used up your daily CPU allowance of 2000 seconds on PythonAnywhere today, so your processes have been put in the tarpit." This leads me to think it might be a resource constraint issue.

Considering this, are there any configurations or tools available that can automatically restart processes when they fail on PythonAnywhere? I'm not entirely sure about the root cause, so any advice or suggestions would be highly appreciated.

Thank you in advance for your assistance!

Basically Always-on tasks are the feature you're looking for and don't need additional configurations (if a script crashes, it will be automatically restarted). But sometimes a code crashes so often that it goes into a loop and can't rise again. Seems that's the case. Could you add more logging to be able to establish where exactly it's crashing and why, and restart it?

I'm attempting to move my code to production and am having some challenges with debugging. I would like to see the error messages when the program crashes, but I'm not sure how to view them.

Here's the current situation: When I run python manage.py qcluster from the command line, everything works as expected. However, when I set up AlwaysOnTasks and run python manage.py qcluster (and then close the console), my custom service.py script crashes about every two days.

I followed the instructions on this link: https://help.pythonanywhere.com/pages/AlwaysOnTasks/ I used the following configuration as recommended:

bash Copy code python3.10 -u /path/to/script.py and added flush=True to my print statements. Even then, no errors are logged.

As a test, I tried the following code in services_test.py:

def q_print(secs):
    try:
        1/0
    except Exception as e:
        print(e, flush=True)

print('service_test done!')

However, the error is not showing up in the "view task log". Currently, the script crashes roughly once every two days, so I'm eager to learn how to capture the error logs when it crashes.

Additionally, I've noticed multiple outputs like:

2023-08-13 11:14:28 - Task preparing to start
Aug 13 11:14:56 service_test done!
Aug 13 11:14:57 service_test done!
...

in the "view task log". Is this expected behavior?

I'd appreciate any guidance or suggestions. Thank you!

Those look like normal output for an always on task. What do you mean by "crashes"?

Thank you for the response.

When I say "crashes", I mean that while initially the task seems to run continuously as shown in the log entries:

2023-08-13 11:14:28 - Task preparing to start
Aug 13 11:14:56 service_test done!
Aug 13 11:14:57 service_test done!
...

At some point, without any apparent reason, it stops running. Is there a recommended way to prevent this from happening or to ensure it runs without interruption?

It looks like your code is restarting very often and thus it may enter a loop of slower restarts. Could you refactor your code to run continuously in a while True loop (preferably with some sleeps between runs), instead of being restarted each time it completes? Also, if your code consists of serveral steps, could you add more logging to see if it's not hanging on a certain step?

A piece of the puzzle has become clear to me. When I run the command python manage.py qcluster and then close the console, after some time, I've noticed that the python manage.py qcluster command stops running. It doesn't seem to be an issue with Always-on tasks. How might I best address this problem? Any insights or recommendations would be greatly appreciated.

One potential solution I've considered is: Having a program, djangoq_service.py, that checks if python manage.py qcluster is running and, if not, executes the command. Would registering this program as an Always-on task be a suitable approach?

I'm eager to hear any suggestions or feedback. Thank you in advance!

The console thing might be unrelated; because consoles are designed for interactive use, we occasionally restart the servers where they run for system maintenance. When you see the command stop running in a console, does the console completely reset? If that's the case, then it's likely to be as a result of that. If, however, your console still shows the python manage.py qcluster command, then it could well be the same issue as you are seeing in always-on tasks.

Regarding having a program to start up the program -- I'm not sure it would help in this case, because from the timings I'm seeing in the logs, it looks like it's crashing pretty much immediately after it starts -- for example, in your log output above it is exiting within 1 second.

I've realized that the issue I'm facing is not with "alwaysontask," but rather with terminal commands stopping unexpectedly. I'd like to delve deeper into this problem; could anyone recommend an appropriate forum where I can do so?

If it's a totally seperate issue than Django Q, maybe start a new forum post with details of the problem?