Forums

[Scheduled Task] ModuleNotFoundError : No module name 'myapp'

Hello everyone,

I saw a few topics about that subject and that guide : but I can't see wshere my mystake is.

I'm trying to execute a python script through PythonAnywhere Scheduled Tasks, but it failed with that error :

Traceback (most recent call last): File "/home/intranethac/intranet/badgeuse/tasks/erreur_badgeuse.py", line 4, in <module> from badgeuse.models import TempsTravail, Periode ModuleNotFoundError: No module named 'badgeuse'

2019-01-18 10:35:36 -- Completed task, took 10.00 seconds, return code was 1.

Here's the task I'm tring to execute :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/python3.7
# coding: utf-8

from badgeuse.models import TempsTravail, Periode
from django.contrib.auth.models import User
from intranet import context_processors
from datetime import date
from badgeuse import functions
from django.template.loader import render_to_string
from django.core.mail import send_mail


def main():

    # Récupération du jour actuel
    today_format = context_processors.today()  # Format chaine de caractères
    today = date.today()

    # Récupération de tous les salariés
    users = User.objects.filter(groups__name="Salariés")

    # Récupération de la période actuelle
    periode = Periode.objects.get(date_debut__lte=today, date_fin__gte=today)

    # Récupération des temps de travail de tous les salariés
    temps_travail = TempsTravail.objects.filter(jour=today)

    # Recherche les salariés ayant oublié de débadgé à ce jour
    temps_travail_inconnu = []

    for value in temps_travail:
        if value.heure_fin is None:
            user = value.user.first_name + ' ' + value.user.last_name
            jour = value.jour.strftime("%m-%d-%Y")
            heure_debut = value.heure_debut.strftime("%H:%M:%S")
            heure_fin = "Inconnu"
            libelle_periode = value.periode.libelle
            temps_travail_inconnu_temp = [user, jour, heure_debut, heure_fin, libelle_periode]
            temps_travail_inconnu.append(temps_travail_inconnu_temp)

    # Recherche les salariés ayant pris moins de 45 min de pause
    # erreur_pause_dejeuner = []

    tab_pause = functions.erreur_pause_dejeuner(today)

    for item in tab_pause:
        item[2] = functions.decompose_time(item[2])

    # Formatage des messages
    message_oubli = "Liste des personnes qui ont oublié de débadgé : \n"
    for value in temps_travail_inconnu:
        message_oubli += value[0] + ' : ' + value[1] + ' ' + ', heure début = ' + value[2] + ', heure fin = ' + value[
            3] + ', période = ' + value[4] + "\n"

    message_pause = "\nListe des temps de pause déjeuner : \n"
    for value in tab_pause:
        message_pause += value[0].user.first_name + " " + value[0].user.last_name + " : " + str(value[0].heure_fin) \
                         + " - " + str(value[1].heure_debut) + " = " + str(value[2][0]) + ":" + str(
            value[2][1]) + ":" + str(value[2][2])

    context = {
        'temps_travail_inconnu': temps_travail_inconnu,
        'erreur_pause_dej': tab_pause
    }

    # Récupération des informations destinées au message électronique
    sujet = "Rapport journalier d'erreur de la badgeuse - " + today.strftime("%d/%m/%Y")
    message = message_oubli + message_pause
    html_message = render_to_string('email/erreur_badgeuse.html', context)
    expediteur = "expediteur@gmail.com"
    destinataire = "destinataire@gmail.com"

    send_mail(
        sujet,
        message,
        expediteur,
        [destinataire],
        fail_silently=False,
        html_message=html_message
    )

    print("Tache quotidienne.")

if __name__ == "__main__":
    main()

And here's my INSTALLED_APPS in settings.py :

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.humanize',
    'intranet',
    'badgeuse',
    'annonce',
    'ckeditor',
    'reportlab',
    'xhtml2pdf',
    'django_xhtml2pdf'
]

My website is working well, and I can use 'badgeus' app everywhere in my project, but not here.

What did I do wrong ?

Thank you.

If you want to run Django code outside the context of a running website, I'd definitely recommend that you structure it as a Django management command. If you don't do that, then when your code is run Django will not be properly configured, and so things won't load properly.

Once you've done that, you can schedule it simply as a command to cd to the correct directory, activate the virtualenv, and then use manage.py to run the command.

cd /home/intranethac/intranet/ && workon myvirtualenv && python manage.py mycommand

...where mycommand is the name of the management command you created.

Hi Giles,

Thank you so much for answering. I followed instructions you wrote and it works perfectly ! I just put my previous code in app/management/commands/mycommand.py, I created a BaseCommand class and I used your command in PythonAnywhere Scheduled Task and all work perfectly.

Thank you again.

PS : I don't know if I can mark this topic as "resolved" ?

Excellent, glad that helped :-)

is intranet the folder where the virtualenv is?

I believe it was rather a root directory for the Django web app. workon is a virtualenvwrapper command that activates the venv given as the argument to it no matter where you call it.