Mailversand von Bildern (in Thread)

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Bonzo1993
User
Beiträge: 28
Registriert: Freitag 28. August 2009, 22:03

hi @ all,

ich habe ein Programm geschrieben, dass mit einer handelsüblichen webcam eine Bewegungserkennung durchführt. Wurde eine Bewegung erkannt, werden die entsprechenden Einzelframes als png auf der Festplatte gespeichert. Diese aufgenommenen Bilder sollen nun in vom Benuzter varriebaren Intervallen als Anhang mit einer Benachrichtigung an eine/mehrere E-Mail Adressen versandt werden. Dazu wird ein eigener Thread gestartet, der sich nur um diese Aufgabe kümmern soll. Der Code dazu sieht bisher wie folgt aus:

Code: Alles auswählen

import time
from threading import Thread
import os

import smtplib
from email.mime.image import MIMEImage 
from email.mime.multipart import MIMEMultipart 

class Mailsync(Thread):
    
    def __init__(self):
        Thread.__init__(self)
        
        self.__lt = time.localtime()
        self.__datum = str(self.__lt[2]) + "." + str(self.__lt[1]) + "." + str(self.__lt[0]) 
        self.__zeit = str(self.__lt[3]) + "_" + str(self.__lt[4]) + "_" + str(self.__lt[5])
    
    
        self.__synctime = 60                                        # User-Setting 
        self.__lastcheck = time.time()
        self.__files = []
        self.__recievers = ["[empfänger]"]        # User-Setting
        self.__directory = "/private/MD/"                            # User-Setting
        self.__path = "C:\Motion Detection\images\\" + str(self.__datum)
        
    def run(self):
        while True:
            # Aktualisierungszeit
            time.sleep(self.__synctime)   
            # Datein zum Versand in Liste speichern    
            for file in os.listdir(self.__path):
                mtime = os.path.getmtime(self.__path + "\\" + file)
                if mtime > self.__lastcheck:
                    self.__files.append(file)
            
            if len(self.__files) != 0:
                COMMASPACE = ", " 
                msg = MIMEMultipart() 
                msg["Subject"] = "Webcam Motion Detection - Report"
                msg["From"] = "md_report@localhost" 
                msg["To"] = COMMASPACE.join(self.__recievers)
                for file in self.__files:
                    fileo = open(self.__path + "\\" + file, "rb")
                    img = MIMEImage(fileo.read()) 
                    fileo.close() 
                    msg.attach(img)
                    self.__files.remove(file)
               
                s = smtplib.SMTP("[absender-mailserver]")
                s.login("[absender-login]", "[absender-pw]")
                s.sendmail("[emfpänger]", "[absender]", msg.as_string()) 
                s.quit()
                print str(time.time()) + ": mail successfully sent!"
            self.__lastcheck = time.time()
[empfänger] steht für die emailadresse die benachrichtigt werden soll (mit den aufgenommenen bildern im Anhang)
[absender] steht im produktionsfall dann für den server des "herstellers" der die Mails versendet


Leider funktioniert der Code aber noch nicht vollständig richtig. Denn anstatt im eingestellten Intervall (hier 60 Sekunden) eine E-Mail mit allen Bildern im Ahang zu versenden, wird eine Mail nach der anderen (oft nur mit ein - zwei bildern im ahang) versendet. Könntet ihr mir da bitte noch helfen?

Viele Grüße
BlackJack

@Bonzo1993: Du entfernst Elemente aus einer Liste über die Du gleichzeitig in einer Schleife iterierst. Dadurch werden Elemente ausgelassen weil beim Entfernen ja alle folgenden Elemente einen Platz "nach vorn" rücken, davon die Schleife aber nichts weiss.

Und die ganzen doppelten führenden Unterstriche könntest Du bei Gelegenheit mal durch einfache ersetzen.

In eine Klasse muss man das IMHO auch nicht unbedingt stecken, da ja eigentlich nur der Inhalt der `run()`-Methode asynchron ausgeführt werden soll -- also eine einfache Funktion.
Bonzo1993
User
Beiträge: 28
Registriert: Freitag 28. August 2009, 22:03

Ich hab jetzt mal versucht die liste erst nachdem sie komplett durchiteriert worden is zu leeren, aber das skript funktz immer noch nicht so wie es soll. Ich vermute es liegt an der Methode wie ich die Bilder bestimme, die in die Liste hinuzugefügt werden. Es sollen eigtl. nur die aktuellen Bilder sein (also alle Bilder die seit dem letzten "Überprüfen" hinzugekommen sind) die zur Liste geaddet werden. Aber ich glaube hier liegt der Fehler, ohne zu wissen an was es genau scheitert:

Code: Alles auswählen

import time
from threading import Thread
import os

import smtplib
from email.mime.image import MIMEImage 
from email.mime.multipart import MIMEMultipart 

class Mailsync(Thread):
    
    def __init__(self):
        Thread.__init__(self)
        
        self._lt = time.localtime()
        self._datum = str(self._lt[2]) + "." + str(self._lt[1]) + "." + str(self._lt[0]) 
        self._zeit = str(self._lt[3]) + "_" + str(self._lt[4]) + "_" + str(self._lt[5])
    
    
        self._synctime = 10                                        # User-Setting 
        self._lastcheck = time.time()
        self._files = []
        self._recievers = [empfängerliste]        # User-Setting
        self._directory = "/private/MD/"                            # User-Setting
        self._path = "C:\Motion Detection\images\\" + str(self._datum)
        
    def run(self):
        while True:
            # Aktualisierungszeit
            time.sleep(self._synctime)   
            # Datein zum Versand in Liste speichern    
            for file in os.listdir(self._path):
                mtime = os.path.getmtime(self._path + "\\" + file)
                if mtime > self._lastcheck:
                    self._files.append(file)
            
            if len(self._files) != 0:
                print(len(self._files))
                COMMASPACE = ", "
                msg = MIMEMultipart()
                msg["Subject"] = "Webcam Motion Detection - Report"
                msg["From"] = "md_report@localhost"
                msg["To"] = COMMASPACE.join(self._recievers)
                for file in self._files:
                    fileo = open(self._path + "\\" + file, "rb")
                    img = MIMEImage(fileo.read()) 
                    fileo.close() 
                    msg.attach(img)
                    
                self._files = []
                
                print(len(self._files))
                
                s = smtplib.SMTP("[MAILSERVER]")
                s.login("[Sender-Mail]", "[PW]")
                s.sendmail("[Absender]", "[EMPFÄNGER]", msg.as_string()) 
                s.quit()
                print str(time.time()) + ": mail successfully sent!"
            self._lastcheck = time.time()
BlackJack

@Bonzo1993: Schau Dir die konkreten Werte für die Zeiten doch mal an.

Warum ist die Dateinamensliste eigentlich an das Objekt gebunden? Es würde doch ausreichen wenn das lokal zur `run()`-Methode ist. Und Du könntest die Liste auch *vor* der Schleife "leeren" bzw. einfach neu erstellen, das wäre IMHO weniger undurchsichtig. Beispiel (ungetestet):

Code: Alles auswählen

    def run(self):
        def check_age(filename):
            mtime = os.path.getmtime(os.path.join(self._path, filename))
            return mtime > self._lastcheck

        while True:
            # Aktualisierungszeit
            time.sleep(self._synctime)   
            # Datein zum Versand in Liste speichern
            filenames = filter(check_age, os.listdir(self._path))
Antworten