Skript im Skript aufrufen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
DGUV-V3
User
Beiträge: 24
Registriert: Dienstag 12. April 2016, 09:50

Hallo mit einander,
ich möchte eine Email mit Anhang versenden habe mir hierfür auch ein kleines Skript geschrieben bei dem ich in der Konsole die Datei übergeben muss.
Mein Code:

Code: Alles auswählen

#!/usr/bin/python

#Sends all files per Mail
#Example usage: python sendMail.py file1.txt, file2.txt ...

import sys, smtplib, os
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import formatdate
from email import Encoders
_encoding = 'utf-8'

class SendMail(object):
  mailtoadress = 'marcel.fromm@bwi-it.de'
  mailfromadress = 'DGUV-V3@web.de'
  smtpserver = 'smtp.web.de'
  username = 'DGUV-V3'
  password = 'Hollywood10'

  def send(self, files):
    # Gather information, prepare mail
    to = self.mailtoadress
    From = self.mailfromadress
    #Subject contains preview of filenames
    if len(files) <= 3: subjAdd = ','.join(files)
    if len(files) > 3: subjAdd = ','.join(files[:3]) + '...'
    subject = 'Pruefauftrag'
    msg = self.prepareMail(From, to, subject, files)

    #Connect to server and send mail
    server = smtplib.SMTP(self.smtpserver)
    server.ehlo() #Has something to do with sending information
    server.starttls() # Use encrypted SSL mode
    server.ehlo() # To make starttls work
    server.login(self.username, self.password)
    failed = server.sendmail(From, to, msg.as_string())
    server.quit()

  def prepareMail(self, From, to, subject, attachments):
    msg = MIMEMultipart()
    msg['From'] = From
    msg['To'] = to
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    # The Body message is empty
    msg.attach( MIMEText("Test") )

    for file in attachments:
      #We could check for mimetypes here, but I'm too lazy
      part = MIMEBase('application', "octet-stream")
      part.set_payload( open(file,"rb").read() )
      Encoders.encode_base64(part)
      part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))
      msg.attach(part)
      #Delete created Tar
    return msg

if __name__ == '__main__':
  mail = SendMail()
  # Send all files included in command line arguments
  mail.send(sys.argv[1:])
Wenn ich das Skript mit python SendMail.py Pruefauftrag.xlsx in der Konsole ausführe funktioniert alles sobald ich das Skript in einem anderen Skript ausführen möchte bekomme ich folgenden Fehler:
python: can't open file '/home/pi/SendMail.py Pruefauftrag.xlsx': [Errno 2]No such file or directory:

Mein Skript hierfür sieht so aus:

Code: Alles auswählen

Import subprocess
Sub = subprocess.Popen (['python', '/home/pi/SendMail.py Pruefauftrag.xlsx'])
#Sub.kill()
Ich hoffe es gibt wer der mir helfen kann und bedanke mich im voraus
lackschuh
User
Beiträge: 281
Registriert: Dienstag 8. Mai 2012, 13:40

Ich würde schleunigst das PW hier ändern und auch bei web.de!!

Edit:
Der absolute Pfad zu Pruefauftrag.xlsx angeben.
DGUV-V3
User
Beiträge: 24
Registriert: Dienstag 12. April 2016, 09:50

lackschuh hat geschrieben:Ich würde schleunigst das PW hier ändern und auch bei web.de!!

Edit:
Der absolute Pfad zu Pruefauftrag.xlsx angeben.
Die Passwörter brauche ich nicht ändern und mit dem absoluten Pfad habe ich auch schon versucht leider ohne erfolg
BlackJack

@DGUV-V3: Du musst da eine Liste mit den Argumenten übergeben. Du übergibst 'python' und dem dann als einziges Agument: '/home/pi/SendMail.py Pruefauftrag.xlsx'. Und nun versucht Python eine Datei mit dem Namen '/home/pi/SendMail.py Pruefauftrag.xlsx' auszuführen, und findet die natürlich nicht. Das muss ein Listeneintrag für die Python-Datei und einer für das Tabellendokument sein.
lackschuh
User
Beiträge: 281
Registriert: Dienstag 8. Mai 2012, 13:40

Nun gut, dann hast du auf web.de dein PW geändert, denn zu Anfang konnte ich mich einloggen ;)

Trotzdem musst du den Pfand angeben:

Code: Alles auswählen

subprocess.Popen (['python', '/home/pi/SendMail.py', '/home/pi/Pruefauftrag.xlsx'])
DGUV-V3
User
Beiträge: 24
Registriert: Dienstag 12. April 2016, 09:50

BlackJack hat geschrieben:@DGUV-V3: Du musst da eine Liste mit den Argumenten übergeben. Du übergibst 'python' und dem dann als einziges Agument: '/home/pi/SendMail.py Pruefauftrag.xlsx'. Und nun versucht Python eine Datei mit dem Namen '/home/pi/SendMail.py Pruefauftrag.xlsx' auszuführen, und findet die natürlich nicht. Das muss ein Listeneintrag für die Python-Datei und einer für das Tabellendokument sein.
Also müsste das ja dann wie Folgt aussehen:

Code: Alles auswählen

import subprocess
Sub = subprocess.Popen (['python','/home/pi/SendMail.py','/home/pi/Pruefauftrag.xlsx']])
Oder habe ich das Falsch verstanden?
BlackJack

@DGUV-V3: Genau. Das hatte lackschuh doch zwischenzeitlich auch als Beispiel gepostet.
lackschuh
User
Beiträge: 281
Registriert: Dienstag 8. Mai 2012, 13:40

Zum Programm gäbe es auch noch einiges zu sagen.

- file ist ein reserviertes Wort
- Zeile 12 wird dir so nichts nützen, in die erste Zeile #coding: utf-8
- in Zeile 51 wird die Datei geöffnet aber nicht mehr geschlossen. Nimm das with Statement
- PEP8
- ....

Ich bin kein OOP Meister, doch der Sinn der Klasse erschließt sich mir hier nicht...

Mal ohne Konsolenparameterübergabe:

Code: Alles auswählen

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

from __future__ import print_function
import smtplib
from os.path import basename
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import COMMASPACE, formatdate

USERNAME = ''
PASSWORD = '' 
FROM_ADR = 'HAns Muster<hans.muster@xyz.com>'


def send_mail(to, subject, text, files=[]):
    assert type(to) == list, "Mut be a list"
    assert type(files) == list, "Must be a list"

    msg = MIMEMultipart()
    msg['From'] = FROM_ADR
    msg['To'] = COMMASPACE.join(to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject
    msg.attach(MIMEText(text, _charset='utf-8'))

    for filename in files:
        with open(filename, "rb") as f:
            msg.attach(MIMEApplication(
                f.read(),
                Content_Disposition='attachment; filename="%s"' % basename(filename),
                Name=basename(filename)
                )
            )

    server = smtplib.SMTP_SSL("smtp.web.de", 465)
    server.ehlo_or_helo_if_needed()
    server.login(USERNAME, PASSWORD)
    server.sendmail(FROM_ADR, to, msg.as_string())
    server.quit()


def main():
    send_mail(["to@adress.com"],
              "Betreff",
              "Text",
              ['deine_datei.csv']
            )

if __name__ == '__main__':
    main()

BlackJack

@lackschuh: Die beiden ``assert``\s sind inhaltlich nicht schön und mindestens das zweite ist schlicht falsch. Ich vermute auch das erste.
lackschuh
User
Beiträge: 281
Registriert: Dienstag 8. Mai 2012, 13:40

Ist IHMO die kürzeste Art zu überprüfen, ob eine Liste übergeben wird oder nicht. Aber für noch kürzere Überprüfungen bin ich offen bzw. für Verbesserungen.

Code: Alles auswählen

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


from email.mime.multipart import MIMEMultipart
from email.utils import COMMASPACE


def send_mail(to):
    #assert type(to) == list, "Muss eine Liste sein ;)"
    msg = MIMEMultipart()
    msg['To'] = COMMASPACE.join(to)
    print msg


send_mail('maine@adresse.com')
BlackJack

@lackschuh: Noch kürzer und richtig wäre gar nicht prüfen. Wenn prüfen dann nicht mit ``assert`` wenn man will das auch tatsächlich immer geprüft wird, und dann nicht auf den konkreten Typ sondern mit `isinstance()` auch abgeleitete Typen erlauben. Aber wie gesagt ist mindestens die zweite Prüfung *viel* zu strikt gewesen. Da geht alles was iterierbar ist. Und das kann man nicht testen ohne tatsächlich iterierbare Objekte auszuschliessen.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@lackschuh: die "Typ"-Prüfung findet mit dem "join" statt. Dann bekommt man auch einen schönen TypeError und weiß dann, was man alles übergeben kann.
BlackJack

@Sirius3: In dem Beispiel halt nicht. Wenn man eine Zeichenkette übergibt, dann ist das ein iterierbares Objekt. Kommt halt nur nicht das gewünschte Ergebnis heraus.

@lackshuh: Damit muss man halt leben. Man kann den Programmierer nicht vor 100% der Dummheiten schützen die er begehen kann. Das wird der schon merken, dass das falsch ist.
DGUV-V3
User
Beiträge: 24
Registriert: Dienstag 12. April 2016, 09:50

Erst einmal recht herzlichen dank für die Hilfreichen Tipps es funktioniert jetzt alles so wie es soll und ich mir vorgestellt habe :o

Da es üblich ist das Emails gleichzeitig an mehrere Empfänger zu senden, bin ich im Moment dabei dies zu implementieren.
Gibt es dabei bestimmte dinge die ich beachten muss oder kann ich eine einfache Auflistung bei der zu Weißung von mailtoadress machen?
Antworten