Au cas où vous auriez la bonté d’aider une moule autodidacte qui apprend Python sur le tas je vous expose mon problème…
Le contexte :
J’ai un script Python3 qui récupère les posts du bouchot pour les stocker dans une base SQLite, actuellement si je veux que ce script tourne de manière régulière je lui colle une entrée dans ma crontab, ça juste marche mais ça ne me semble pas propre. Donc ce que je voudrais faire c’est que ce script puisse tourner en tâche de fond et faire sa requête GET pas forcément à intervalles réguliers mais en fonction du nombre de posts récupérés à la dernière exécution. Je me dis donc que ce serait bien que ce script soit « daemonizé ».
Donc vu que j’y connais rien et que je suis une buse complète je me suis dit qu’il faudrait commencer par un test simple. Donc voilà ce que je fais :
Prout.py :
#!/usr/bin/env python3
from time import sleep
def prout():
print("prout !")
sleep(3)
while True:
prout()
daemon_prout.py :
#!/usr/bin/env python3
import daemon
from Prout import prout
context = daemon.DaemonContext()
with context:
prout()
Quand je lance daemon_prout.py ça flatule bien toutes les 3 secondes, par contre ça ne le fait pas en arrière plan…
Qu’est-ce que je fais mal ?
J’ai essayé d’autres approches, soit ça me rend bien la main mais ça "prout !" pas, soit ça "prout !" mais ça ne me rend pas la main (ça ne tourne donc pas en tâche de fond).
Je pense qu’il y a des choses à paramétrer sur l’objet context mais je suis perdu. J’ai essayé avec context.files_preserves = [1,2,3] mais ça ne change rien.
Je sais que je pourrais lancer mon script à l’aide de nohup mais je voudrais bien comprendre le principe des daemons en Python3…
Moulesquement.
# j'y connais rien mais faut vraiment que je m'y mettes
Posté par NeoX . Évalué à 4.
ici il semble y avoir un exemple
http://stackoverflow.com/questions/4637420/efficient-python-daemon
[^] # Re: j'y connais rien mais faut vraiment que je m'y mettes
Posté par Marotte ⛧ . Évalué à 2.
Merci je vais essayer ça.
[^] # Re: j'y connais rien mais faut vraiment que je m'y mettes
Posté par Marotte ⛧ . Évalué à 2.
Merci beaucoup pour ta réponse. Alors voilà le code que j’ai pour arriver à ce que je veux. Bon OK ce que je veux est assez débile en vérité, je ne vais pas faire ça pour mon programme final mais voilà :
Le programme tourne bien en tâche de fond mais continue de flatuler sur la sortie standard…
Comme tu vois j’ai commenté le
if __name__ == "__main__"
, pour voir si ça marchait sans… va falloir que j’aille lire le bon post SO qui traite de cette incantation pour être moins bête…Bon, en l’état pour « tuer » ce daemon je dois faire un kill… plus qu’à trouver comment je peux implémenter un
./Prout.py start
pour le démarrer et un./Prout.py stop
pour l’arrêter… et bien sûr je ne vais pas rediriger la stdout vers sys.stdout mais plutôt vers un fichier standard.Merci NeoX, tu gères !
[^] # Re: j'y connais rien mais faut vraiment que je m'y mettes
Posté par Marotte ⛧ . Évalué à 3.
À la lecture de http://stackoverflow.com/questions/419163/what-does-if-name-main-do
je pense que j’ai intérêt à le mettre !
^^
# Pour quoi faire ?
Posté par RoPP . Évalué à 6.
Sinon, tu utilises une distrib moderne et tu laisses systemd s’occuper de tout !
/etc/systemd/system/prout.service :
[^] # Re: Pour quoi faire ?
Posté par Marotte ⛧ . Évalué à 2.
Oui c’est une solution… Par contre je ne veux pas lancer ce script en tant que root (j’imagine que systemd permet de spécifier un utilisateur, faut que je RTFM je sais…)
Par contre je suppose que ça permet quand même moins de souplesse qu’utiliser la lib daemon de Python…
[^] # Re: Pour quoi faire ?
Posté par RoPP . Évalué à 6.
Allez, je t’aide :)
Par contre, je ne suis pas sûr de voir en quoi tu aurais moins de souplesse en laissant systemd faire son taf… je veux bien un exemple :)
[^] # Re: Pour quoi faire ?
Posté par Marotte ⛧ . Évalué à 2.
Je ne connais pas assez la lib daemon pour te trouver un exemple et peut-être bien que ça n’offre aucune souplesse supplémentaire. Alors j’en un autre argument à avancer : ne pas être dépendant de systemd ?
[^] # Re: Pour quoi faire ?
Posté par xcomcmdr . Évalué à 1.
Ne pas dépendre de systemd, ou éviter systemd par religion ?
"Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)
[^] # Re: Pour quoi faire ?
Posté par Marotte ⛧ . Évalué à 3.
C’est surtout que je souhaite apprendre le Python et si je peux apprendre à faire des scripts multi-plateformes je préférerais. Sinon systemd je l’utilise depuis un petit moment sur mon poste personnel, j’en suis très content.
J’ai réussi à daemonizé mon script (pas la prouteuse, le script qui récupère les posts à intervalle réguliers…) me reste à apprendre à le contrôler (commandes start, stop…) et là je m’aperçois qu’un Ctrl+d, qui va donc fermer le shell avec lequel j’ai lancé le script l’arrête :/ Maintenant que j’ai compris la base va falloir que que je lise plus en profondeur la doc de la lib daemon…
[^] # Re: Pour quoi faire ?
Posté par Anthony Jaguenaud . Évalué à 2.
Comme on est vendredi…
Autant, je comprends bien que systemd => une distrib moderne, autant je ne vois pas bien l’équivalence…
Une distrib moderne ≠> systemd.
# supervisord
Posté par Benoît Laurent (site web personnel) . Évalué à 3.
Le plus simple est certainement de laisse faire le boulot de "daemonization" à http://supervisord.org/
[^] # Re: supervisord
Posté par Juke (site web personnel) . Évalué à 3.
Quel est l'avantage par rapport à utiliser le systeme d'init de la distrib ?
[^] # Re: supervisord
Posté par flan (site web personnel) . Évalué à 2.
systemd supprime en bonne partie les deux derniers arguments. Perso, je faisais du supervisor, et je passe à systemd.
# Pourquoi tu dis que cela ne marche pas
Posté par TheBreton . Évalué à 3.
Préambule:
J'ai dernièrement réaliser un daemon en python (2.7) pour une cible embarqué, je te file un lien vers le tuto que j'ai suivi (et qui te sera très utile voir fin du post) et je n'ai pas porté le binding daemon lib sur ma cible mais utilisé les fonctions native du système (lib os) .
Question : Tu dis que ton code ne marche pas en arrière plan. Peut tu préciser (1) Tu ne vois pas les prout et (2) quand tu fais un 'ps' vois tu un PID associé à ton daemon ?
Si (1)=TRUE et (2)=Je vois mon daemon dans les pid, alors ta conclusion est erronée et ton daemon tourne. Simplement du fais qu'il ne dispose pas de la redirection de stdin, stdout et stderr tu ne vois pas d'affichage sur ta console.
Si (2)=Je ne vois rien, alors tu as raison, la daemonisation en fonctionne pas.
Référence : (Il faut rendre à cesar…etc)
Voici en version 2.7
Voici la version en 3.x
Bonne flatulence
[^] # Re: Pourquoi tu dis que cela ne marche pas
Posté par Marotte ⛧ . Évalué à 2.
Lorsque je fais un ps je vois bien un
python3 ./daemon_prout.py
mais ça me paraît normal vu que mon programme Prout.py fait unwhile True
…Je vais essayer la solution de NeoX (je n’ai pas besoin de deux fichiers déjà…) je vais faire simple. J’étais moi aussi tombé sur cette manière de faire en « pur Python », sans utiliser de lib dédiée, je m’y essayerai si la première solution ne fonctionne pas. Un grand merci pour ton aide.
[^] # Re: Pourquoi tu dis que cela ne marche pas
Posté par TheBreton . Évalué à 2.
Mais de rien, donc si ton daemon est présent et tourne en mémoire c'est sans doute un simple soucis de pipe.
je te suggere de faire
import sys
et
daemon.DaemonContext(stdout=sys.stdout)
pour récupérer le pipe de sortie et ainsi avoir l'affichage des sortie de ton daemon
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.