iznobe
Posts: 107
Joined: Sun Feb 05, 2017 4:14 pm

erreur code python qui marche 2 fois : Segmentation fault

Mon Jul 08, 2019 7:56 am

Bonjour ,

toujours a propos du meme projet que j ' ai depuis un petit moment ,

le code marche mais apres " 2 tours " ne fonctionne plus :?

voici le resultat obtenu du code en question :

Code: Select all

09:43:13 le 08/07/2019 , Initialisation sur le pin : 16

09:44:03 le 08/07/2019 , le flotteur est passe en position haute

09:44:22 le 08/07/2019 , le flotteur est en position normale : basse

09:44:33 le 08/07/2019 , le flotteur est passe en position haute

09:45:43 le 08/07/2019 , le flotteur est en position normale : basse

Segmentation fault


------------------
(program exited with code: 139)
Press return to continue

et le code ;) :

Code: Select all

#! /usr/bin/python
# coding: utf-8

import RPi.GPIO as GPIO
import time
from datetime import datetime

GPIO.setmode(GPIO.BCM) # board = emplacements physiques , BCM emplacements logiques du proc

# les pins 15 , 8 , 36 sont inutilisables ...
# lorsque le flotteur est en position normale ( basse ) , le contacteur est alimentee et permet aux pompes et aux electrovannes 
# de gerer le systeme automatiquement, le PI recoit un signal LOW sur son PIN car relie a la masse .
# En cas de fuite , le flotteur passe en position haute , le contacteur n ' alimente plus les pompes et electrovannes du local technique 
# afin de limiter les degats du a la fuite d' eau . le PI recoit un signal HIGH car le PIN est placé en pull UP .
# reellement le PIN n ' est plus connecte a rien car le contacteur est ouvert justement !

#global pin_flotteur
pin_flotteur=16
GPIO.setup(pin_flotteur, GPIO.IN, pull_up_down=GPIO.PUD_UP) # en mode entree Tout Ou Rien

#GPIO.setup(GPIO_LEFT, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# On se met en pullup, l'état du GPIO est donc à 1 par défaut, on détectera un appui lorsqu'il passe à zero (et donc FALLING) ,
# donc il faut cabler sur masse quand contact , quand il n ' y a pas de contact on reste en etat HIGH

# Fonctions
def ecrire_log ( message , date ) :
    fichier = open("/home/pi/projets_auto/logs/envoi_mail_auto.log", "a")
    
    if date == 0 :
        log = message
    else :
        now=(datetime.now().strftime("%H:%M:%S le %d/%m/%Y , "))
        log = (now + message + "\n")

    fichier.write(log)
    fichier.close()
    
    print(log)

########################################################################
def my_callback (pin_flotteur) : # gestion des actions en fonction de l ' etat du PIN d' entree
    
    
    time.sleep(1) # ici on faut un debounce : on attend 0.1s pour confirmer ou non l'appui
    state = GPIO.input(pin_flotteur) # lecture etat de l ' entree
    print(state)
    # Si on est toujours dans l' etat bas apres detection du falling
    if not state : # permet de faire les actions une seule fois par cycle de montee descente flotteur grace au time.sleep dans la boucle while
        GPIO.remove_event_detect(pin_flotteur) # on évite un autre appel pendant qu'on traite celui déjà présent
        ecrire_log("le flotteur est passe en position haute",1)
        state = GPIO.input(pin_flotteur)
    
        while not state : # on attend le retour du contacteur.
            #ecrire_log("on attend le retour a l ' etat normal du flotteur",0)
            time.sleep(1) # on attend le retour a l ' etat normal du flotteur
            state = GPIO.input(pin_flotteur) # lecture etat de l ' entree
        
            if state : # le flotteur est repasse en position basse , donc le contacteur fait contact et remet le pin a 0
                ecrire_log("le flotteur est en position normale : basse",1)
                GPIO.add_event_detect(pin_flotteur, GPIO.FALLING, callback=my_callback, bouncetime=1000)
                # on remet la détection maintenant que le traitement a été fait
                
########################################################################

GPIO.add_event_detect(pin_flotteur, GPIO.FALLING, callback=my_callback, bouncetime=1000) # GPIO.FALLING GPIO.BOTH GPIO.RISING  , callback=my_callback
ecrire_log ("Initialisation sur le pin : " + str(pin_flotteur),1)

while True :
    time.sleep(1)
Quel est le soucis , car apres plusieurs recherche ce weekend , je n ' ai pas trouvé quelquechose de concluant ...

merci pour votre aide
Last edited by iznobe on Tue Jul 09, 2019 9:42 am, edited 3 times in total.

iznobe
Posts: 107
Joined: Sun Feb 05, 2017 4:14 pm

Re: erreur code python qui marche 2 fois

Mon Jul 08, 2019 8:31 am

Je rectifie le tir :

Apres reecriture de la fonction , plus d' erreur : ( meme si je ne comprends pas pourquoi pas grave :) )

Code: Select all

def ecrire_log ( message , date ) :
    fichier = open("/home/pi/projets_auto/logs/envoi_mail_auto.log", "a")
    
    log = (message + "\n")
    if date == 1 :
        now=(datetime.now().strftime("%H:%M:%S le %d/%m/%Y , "))
        log = (now + message + "\n")

    fichier.write(log)
    fichier.close()
    
    print(log)

iznobe
Posts: 107
Joined: Sun Feb 05, 2017 4:14 pm

Re: erreur code python qui marche 2 fois

Mon Jul 08, 2019 1:50 pm

bon ben en fait , non parfois cela fonctionne plus de deux fois , mais l ' erreur revient quand meme :(

tqhien
Posts: 28
Joined: Thu Feb 02, 2012 10:07 am

Re: erreur code python qui marche 2 fois

Tue Jul 09, 2019 9:43 am

Pour les écritures de fichier, je te conseille de passer plutôt sur la syntaxe suivante :

Code: Select all

try:
    with open("output", "a") as outfile:
        outfile.write('Hello World')
except IOError:
    print ('oops!')
Cela permet d'ouvrir, d'écrire et refermer le fichier tout de suite (with, pas besoin de close) tout en interceptant les erreurs d'entrée/sortie (try/except). L'erreur 139 signifie "fichier introuvable".

Hien.

iznobe
Posts: 107
Joined: Sun Feb 05, 2017 4:14 pm

Re: erreur code python qui marche 2 fois : Segmentation fault

Tue Jul 09, 2019 10:36 am

Salut et merci pour votre aide ;)

A priori le probleme ne se pose plus lorsque je commente la fonction sendmail dans le callback ...

j ' ai fait une boucle infinie dans un fichier test et exactement la meme fonction send mail , aucun probleme .

j ' ai verifie qu il me reste de la place en memoire , aucun soucis la commande top m ' annonce 500 Mo .

j 'ai tente de gerer les erreurs globalement avec :

Code: Select all

import sys

def erreur_log (type, value, traceback) :
    fichier = open("/home/pi/projets_auto/logs/erreur.log", "a")
    now=(datetime.now().strftime("le %d/%m/%Y a : %H:%M:%S , "))
    fichier.write(now + str(type) + str(value) + str(traceback) + "\n")
    fichier.close()
    
sys.excepthook = erreur_log

ca ne me remonte rien , pourtant si j ' insere dans mon code :

Code: Select all

1/0
, la ca fonctionne et m ' ecrit bien dans le fichier log l' erreur et son detail :?

lorsque je fais mes essais sans votre façon d' ecrire dans le fichier , aucun probleme cela marche sans soucis au niveau de l' ecriture de fichier , d' ailleurs j ' ai posté le fichier log dans lequel il ecrit dans mon premier post et on voit bien que cela fonctionne .

j ' ai remplace mon code par le votre pour l' ecriture de fichier et meme soucis , a savoir : segmentation fault , erreur 139 , et ca ecrit bien dans le meme fichier sans probleme .

il suffit que je commente la fonction send mail et la tout est ok :evil:

bizzarre ce probleme sachant que la fonction separement marche sans aucun probleme en boucle ...

quand je passe la commande " ulimit -s " ( je ne me rappelle plus exactement mais ca s 'en approche ) ca me renvoie 8192 , j ' ai vu je ne sais plus ou qu on pouvait augmenter cette limite , j ' ai teste de mettre 16384 , l ' erreur met environ deux fois plus de temps a apparaitre , mais revient tout de meme , comme si il stockait en memoire a chaque fois la fonction , et qu ' au bout d ' un certain nombre de fois , il y avait un depassement de memoire ...

je ne sais plus trop quoi tenter :roll:
Last edited by iznobe on Tue Jul 09, 2019 2:14 pm, edited 1 time in total.

iznobe
Posts: 107
Joined: Sun Feb 05, 2017 4:14 pm

Re: erreur code python qui marche 2 fois : Segmentation fault

Tue Jul 09, 2019 2:08 pm

je viens d' essayer de faire la meme chose en mettant la fonction envoi_mail dans un fichier et en faisant un import :

Code: Select all

from mail import envoi_mail
puis dans la fonction de callback :

Code: Select all

envoi_mail()
exactement le meme resultat erreur segmentation code 139 :o , si je lance le fichier mail.py aucun soucis ...

voici le code du fichier en question :

Code: Select all

#! /usr/bin/python
# coding: utf-8

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

def envoi_mail() : # expeditions multiples
    msg = MIMEMultipart()
    msg["Subject"] = "Example"
    msg["From"] = "X@gmail.com"
    msg["To"] = "X@gmail.com"
    body = MIMEText("example email body")
    msg.attach(body)
    
    smtp = smtplib.SMTP("smtp.gmail.com", 587)
    smtp.starttls()
    smtp.login("X@gmail.com", "XXXXXXXX")
    smtp.sendmail(msg["From"], msg["To"].split(","), msg.as_string())
    smtp.quit()
je ne vois pas vraiment ce qui peut faire ce probleme

Dans thon python IDE voici le resultat :

Code: Select all

Backend terminated (returncode: -11)
Fatal Python error: Segmentation fault

Thread 0x76fcaad0 (most recent call first):
  File "/home/pi/projets_auto/python/testeur.test.py", line 146 in <module>
  File "/usr/lib/python3/dist-packages/thonny/backend.py", line 1232 in _execute_prepared_user_code
  File "/usr/lib/python3/dist-packages/thonny/backend.py", line 1158 in wrapper
  File "/usr/lib/python3/dist-packages/thonny/backend.py", line 1171 in wrapper
  File "/usr/lib/python3/dist-packages/thonny/backend.py", line 1219 in execute_source
  File "/usr/lib/python3/dist-packages/thonny/backend.py", line 853 in _execute_source
  File "/usr/lib/python3/dist-packages/thonny/backend.py", line 840 in _execute_file
  File "/usr/lib/python3/dist-packages/thonny/backend.py", line 400 in _cmd_Run
  File "/usr/lib/python3/dist-packages/thonny/backend.py", line 217 in handle_command
  File "/usr/lib/python3/dist-packages/thonny/backend.py", line 162 in mainloop
  File "/usr/lib/python3/dist-packages/thonny/backend_launcher.py", line 70 in <module>
Use 'Stop/Restart' to restart the backend ...
avec le fichier original testeur.test.py :

Code: Select all

#! /usr/bin/python
# coding: utf-8
import sys
import RPi.GPIO as GPIO
import time
from datetime import datetime
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

GPIO.setmode(GPIO.BCM) # board = emplacements physiques , BCM emplacements logiques du proc

# les pins 15 , 8 , 36 sont inutilisables ...
# lorsque le flotteur est en position normale ( basse ) , le contacteur est alimentee et permet aux pompes et aux electrovannes 
# de gerer le systeme automatiquement, le PI recoit un signal LOW sur son PIN car relie a la masse .
# En cas de fuite , le flotteur passe en position haute , le contacteur n ' alimente plus les pompes et electrovannes du local technique 
# afin de limiter les degats du a la fuite d' eau . le PI recoit un signal HIGH car le PIN est placé en pull UP .
# reellement le PIN n ' est plus connecte a rien car le contacteur est ouvert justement !

#global pin_flotteur
pin_flotteur=16
GPIO.setup(pin_flotteur, GPIO.IN, pull_up_down=GPIO.PUD_UP) # en mode entree Tout Ou Rien
#global log
log=1 # mettre 0 pour desactiver et 1 pour activer ou True False
# gerer les erreurs :


#GPIO.setup(GPIO_LEFT, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# On se met en pullup, l'état du GPIO est donc à 1 par défaut, on détectera un appui lorsqu'il passe à zero (et donc FALLING) ,
# donc il faut cabler sur masse quand contact , quand il n ' y a pas de contact on reste en etat HIGH par defaut du au pull_up.

# Fonctions
# def erreur_log (type, value, traceback) :
    # fichier = open("/home/pi/projets_auto/logs/erreur.log", "a")
    # now=(datetime.now().strftime("le %d/%m/%Y a : %H:%M:%S , "))
    # fichier.write(now + str(type) + str(value) + str(traceback) + "\n")
    # fichier.close()
    
# sys.excepthook = erreur_log
    
if log :
    def ecrire_log ( message , date ) :
        try:
            with open("/home/pi/projets_auto/logs/envoi_mail_auto.log", "a") as outfile:
                ecrire = message
                if date :
                    now=(datetime.now().strftime("le %d/%m/%Y a : %H:%M:%S , "))
                    ecrire = (now + message)
                    
                outfile.write(ecrire + "\n")
        except IOError:
            print ('oops!')
            
        print(ecrire)

def envoi_mail() : # expeditions multiples
    msg = MIMEMultipart()
    msg["Subject"] = "Example"
    msg["From"] = "XXxx@gmail.com"
    msg["To"] = "XXxx@gmail.com"
    body = MIMEText("example email body")
    msg.attach(body)
    smtp = smtplib.SMTP("smtp.gmail.com", 587)
    smtp.starttls()
    smtp.login("XXxx@gmail.com", "XXXXXXXX")
    smtp.sendmail(msg["From"], msg["To"].split(","), msg.as_string())
    smtp.quit()
    
########################################################################
def my_callback (pin_flotteur) : # gestion des actions en fonction de l ' etat du PIN d' entree
    GPIO.remove_event_detect(pin_flotteur) # on évite un autre appel pendant qu'on traite celui déjà présent
    time.sleep(1) # ici on faut un debounce : on attend 0.1s pour confirmer ou non l'appui
    state_initial = state_final = state_attente = GPIO.input(pin_flotteur) # lecture etat de l ' entree
    #state_attente = GPIO.input(pin_flotteur)
    #state_final = GPIO.input(pin_flotteur)
    if log :
        print("state_initial : " + str(state_initial))
        
    while state_initial :
        time.sleep(2)
        state_initial = GPIO.input(pin_flotteur)
        if not state_initial :
            state_attente = GPIO.input(pin_flotteur)
            print("state_attente : " + str(state_attente))

    # Si on est toujours dans l' etat bas apres detection du falling
    if not state_attente : # permet de faire les actions une seule fois par cycle de montee descente flotteur grace au time.sleep dans la boucle while
        envoi_mail()
        if log :
            ecrire_log("le flotteur est passe en position haute",1)
    
    #state = GPIO.input(pin_flotteur)

    while not state_attente : # on attend le retour du contacteur.
        time.sleep(1) # on attend le retour a l ' etat normal du flotteur
        if log :
            ecrire_log("on attend le retour a l etat normal du flotteur",0)
        
        state_attente = GPIO.input(pin_flotteur)
        if state_attente :
            state_final = GPIO.input(pin_flotteur) # lecture etat de l ' entree

    if state_final : # le flotteur est repasse en position basse , donc le contacteur fait contact et remet le pin a 0
        if log :
            ecrire_log("le flotteur est en position normale = basse",1)
    GPIO.add_event_detect(pin_flotteur, GPIO.FALLING, callback=my_callback, bouncetime=1000)
                # on remet la détection maintenant que le traitement a été fait
    

########################################################################

GPIO.add_event_detect(pin_flotteur, GPIO.FALLING, callback=my_callback, bouncetime=1000) # GPIO.FALLING GPIO.BOTH GPIO.RISING  , callback=my_callback

if log :
    ecrire_log ( ("Initialisation sur le pin : " + (str(pin_flotteur)) ),1)

while (True):
    time.sleep(10)


si je commente la ligne 116 et donc n ' envoie plus le mail , tout marche nickel :roll: mais bon ca sert plus a grand chose :lol:

si vous avez des idees , je suis preneur


iznobe
Posts: 107
Joined: Sun Feb 05, 2017 4:14 pm

Re: erreur code python qui marche 2 fois : Segmentation fault

Wed Jul 10, 2019 8:09 am

totoharibo wrote:
Wed Jul 10, 2019 5:49 am
bash ?
salut ,

pourquoi pas mais comment fait on pour envoyer un mail en bash par telnet openssl ?

iznobe
Posts: 107
Joined: Sun Feb 05, 2017 4:14 pm

Re: erreur code python qui marche 2 fois : Segmentation fault

Wed Jul 10, 2019 9:52 am

j ' ai repris votre code dans un autre post et y ait inserer un appel au fichier python pour envoyer un mail et ca marche au premier abord parfaitement :)

Cependant vu mon ignorance en bash , je ne comprends que tres peu de chose dans votre code qui me parait fort bien evolue !!!

Si vous pourriez me detaillez ( quand vous aurez un peu de temps ) ce que fait chaque commande , car j ' ai vraiment du mal a digerer tout cela ca serait top .

en tout cas ca parait fonctionner a merveille :D

Code: Select all

#!/bin/bash

#init hard
#.	../../init_acquisition
FLOTTEUR=16
##################################################################
#init
function init {

echo  "init"
gpio -g mode "$FLOTTEUR" in # -g  active equivalent mode GPIO.BCM ( logique ) , physique sans le -g
}

##################################################################
#teste BP
function bouton {
#inter
export proc_bouton
#echo "bb"
inter=$(gpio -g read $FLOTTEUR )
echo "==$inter=="
( while [ 1 ] ; do
	lit=$(gpio -g read $FLOTTEUR )
	if [ $lit -ne $inter ] ; then
		inter=$lit
		echo "**$inter**"		
		if  [ $lit -eq 0 ] ; then
			python /home/pi/projets_auto/python/mail.py # envoi du mail
			echo "mail envoye"
			kill -USR1 $$
			echo "---->kill"
			
		fi
	fi
	sleep 0.1
	done
) &
proc_bouton=$!
}
##################################################################
##################################################################
bouge=0
trap "bouge=1" SIGUSR1
#on démarre
init

echo $$

#inter
bouton

#boucle de fond
while [ 1 ] ; do
	if [ $bouge -ne 0 ] ; then
		echo "---->bouge"
		bouge=0
		#break
	fi
	sleep 0.5
done

#arrete procs
kill $proc_bouton

export proc button , c ' est pour lancer un second process ? et kill a la fin , le stopper ?

$$ recupere le pid du process ?

quel interet de kill les process ?

du coup la boucle de fond sert a quoi ? un seul process pour gerer le flotteur ne suffirait pas ?

merci beaucoup pour votre temsp !

totoharibo
Posts: 4178
Joined: Thu Jan 24, 2013 8:43 am

Re: erreur code python qui marche 2 fois : Segmentation fault

Wed Jul 10, 2019 12:04 pm

pour les mails en bash un lien au hasard :
https://tecadmin.net/ways-to-send-email ... mand-line/

plein de tutoriaux existent.
bash : OK on change de monde.

J'ai aussi fait du python.
traitement de films argentique 8 et super8 image par image. CV2 est une bonne bibliothèque pour ça.
L'acquisition était en bash/C.

Je ne pense pas que l'acquisition je m'en serai tiré en python :lol:

iznobe
Posts: 107
Joined: Sun Feb 05, 2017 4:14 pm

Re: erreur code python qui marche 2 fois : Segmentation fault

Wed Jul 10, 2019 1:52 pm

Par contre j ' ai a nouveau des faux positifs sur le long terme du coup :?

j ' ai mis :

Code: Select all

sleep 0.5
dans la fonction button , mais encore de faux positifs , est ce que un controle suplementaire peut empecher ce phenomene , style englobe la fonction button dans une condition de plus ?

Votre lien est interressant , mais sur pi , il y a send mail d' installe par defaut .
Telnet me parait dangereux , et les liens que j ' ai regarde ce matin parlait tres peu de STARTTLS avec bash voire pas du tout .
le seul que j ' ai trouve ne permettait que de faire la connexion , la communication (commandes EHLO et SMTP n ' etait pas traité ) .

ouhla , je ne suis pas programmeur , j ' ai failli faire une crise cardiaque en lisant votre post precedent ! :lol:

Non serieusement , bravo pour votre cursus et votre talent que je suis incapable d ' apprecier a sa juste valeur par manque de connaissance :roll:

ca doit etre interressant de pouvoir faire ce genre de projet , mais il faut maitrise , j ' ai encore du travail avant d' arriver a faire ce genre de chose :D

EDIT : j ' ai rajouté une condition et un sleep :

Code: Select all

#!/bin/bash
#essai de clignotant des  2 couleurs

#init hard
#.	../../init_acquisition
FLOTTEUR=16
##################################################################
#init
function init {

echo  "init"
gpio -g mode "$FLOTTEUR" in # -g  active equivalent mode GPIO.BCM ( logique ) , physique sans le -g
}

##################################################################
#teste BP
function bouton {
#inter
export proc_bouton
inter=$(gpio -g read $FLOTTEUR)
echo "==$inter=="
( while [ 1 ] ; do
	
	lit=$(gpio -g read $FLOTTEUR)
	if [ $lit -ne $inter ] ; then
		sleep 0.5
		lit=$(gpio -g read $FLOTTEUR)
		if [ $lit -ne $inter ] ; then
			inter=$lit
			echo "**$inter**"		
			if  [ $lit -eq 0 ] ; then
				python /home/pi/projets_auto/python/mail.py # envoi du mail
				echo "mail envoye"
				kill -USR1 $$
				echo "---->kill"
			fi
		fi
	fi
	sleep 0.5
	done
) &
proc_bouton=$!
}
##################################################################
##################################################################
bouge=0
trap "bouge=1" SIGUSR1
#on démarre
init

echo $$

#inter
bouton

#boucle de fond
while [ 1 ] ; do
	if [ $bouge -ne 0 ] ; then
		echo "---->bouge"
		bouge=0
		#break
	fi
	sleep 0.5
done

#arrete procs
kill $proc_bouton

je teste ca sur la duree , mais je ne suis pas certain que c' est la bonne maniere de proceder :roll:

Return to “Français”