Seite 1 von 2
Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Donnerstag 9. Juni 2022, 15:43
von dermaxem
Hallo,
ich bin neu in der Materie und kenne noch nicht alle Funktionen, habe auch noch keinen Lern-Kursus gemacht.
Für eine Terrarium-Steuerung habe ich mir was überlegt, das aber - wegen fehlender Programmiererfahrung - viel auf der Beispiel-Datei des Sensor-Lieferant beruht.
(AZ-Delivery, GY-21-Sensor am RASPI)
Ist bestimmt auch chicer via Funktionen zu lösen, aber würde für mein Urlaubs-Script erst mal langen.
In dem Script (Script1) wird von einem Sensor die Temperatur und Luftfeuchte abgefragt. Funktioniert auch alles wie es soll.
Das Script habe ich mir angepasst, mit Daum/Uhrzeit versehen, dann einen Tag- und Nachmodus definiert und dann die Werte entsprechend behandelt.
Nun möchte ich für einen bestimmten Fall eine E-Mail senden, bzw noch eine URL aufrufen.
Dafür habe ich ein zweites Script "gebastelt", das mir eine E-Mail sendet. Diesem 2ten Script kann ich 2 Werte mit angeben, die via "sys.argv[x]" mit in der Mail auftauchen.
Wenn ich das so in der Konsole aufrufe "
" dann erzeugt mir das die Mail, in der dann die Werte auch erscheinen. Klappt soweit
Wie kann ich beim Aufrufen des 2. Mail-Scriptes, aus dem ersten Script heraus, die 2 Werte mit an das Mail-Script übergeben?
Habe es mit
versucht, erhalte dafür einen SyntaxError: Invalid Syntax.
Gesucht habe ich dazu, aber leider keine Lösung gefunden, die ich auch verstanden hätte.
Hier was ich gefunden habe, aber nicht weiss, wie ich es umsetzten kann:
Code: Alles auswählen
with open("somefile.py") as f:
code = compile(f.read(), "somefile.py", 'exec')
exec(code, global_vars, local_vars)
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Freitag 10. Juni 2022, 09:40
von Kebap
Ich würde eine andere Lösung wählen, und endweder die Mailfunktion in das erste Skript mit aufnehmen, oder das zweite Skript per "import" ins erste Skript einbinden. Dann kannst du dessen Funktionen auch dort benutzen. Du hast doch Funktionen benutzt, oder?

Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Freitag 10. Juni 2022, 10:39
von __blackjack__
@dermaxem: Vergiss `exec()`, schreib das `mail`-Modul so, dass da eine Funktion drin ist, die diese zwei Argumente erwartet und eine Mail verschickt wenn man sie aufruft. Und die Funktion rufst Du dann halt einfach auf.
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Dienstag 21. Juni 2022, 11:14
von dermaxem
habe es nu so versucht, aber einen Fehler erhalten.
Den hab ich gegooglet, versucht als "str" zu setzten, aber bekomme immer noch den gleichen Fehler.
Was mache ich falsch?
Code: Alles auswählen
Traceback (most recent call last):
File "/home/pi/test2.py", line 35, in <module>
exec(open(str("mail.py", temp, humidity)).read())
TypeError: str() argument 2 must be str, not float
Ziel: das externe "mail.py"-Script aufzurufen und diesem die 2 Parameter zu übergeben.
die Werte der Parameter sind jedoch Zahlen.
Wandel ich die auch um, dann kommt:
Code: Alles auswählen
Traceback (most recent call last):
File "/home/pi/test2.py", line 35, in <module>
exec(open(str("mail.py", str(temp), str(humidity))).read())
TypeError: decoding str is not supported
und versuche ich es so:
Code: Alles auswählen
Traceback (most recent call last):
File "/home/pi/test2.py", line 35, in <module>
exec(open("mail.py", str(temp), str(humidity)).read())
TypeError: an integer is required (got type str)
kommt es auch zum Fehler.
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Dienstag 21. Juni 2022, 11:21
von __blackjack__
@dermaxem: Falsch daran ist wie schon gesagt `exec()`. Vergiss das.
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Dienstag 21. Juni 2022, 11:25
von Sirius3
Das richtige Vorgehen ist es, ein Module `mail` zu haben, in dem es z.B. eine Funktion `send_mail` gibt:
Code: Alles auswählen
from mail import send_mail
send_mail(temperature, humidity)
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Mittwoch 22. Juni 2022, 10:45
von dermaxem
da ich es nicht anders kann, habe ich die Imports des Mail-Scripts mit in den oberen Bereich des Haupt-Scripts gepackt.
Dann eine funktion
"def mailen(grund, now, temp, humidity, spray)"
angelegt und dann da eingerückt alles, was in dem Mail.py-cript drinn war, auisser eben die Import-Zeilen am Anfang.
dann habe ich eine Funktion
"messen(channel)" im Script, da sind paar if-Abfragen. Darauf hin werden werte fü die Variablen zum vermailen gesetzt
und dann mit "mailen(grund, ...) " aufgerufen.
Das gibt dann einen Fehler:
"Fehler: <built-in function exec>"
HIer mal mein Script als Basis:
Code: Alles auswählen
# -*- coding: utf-8 -*-
import thingspeak
import time
import board
import busio
import smtplib
import sys
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from adafruit_htu21d import HTU21D
def messe(channel):
try:
#das ganzemess-gedöhns
if dies
grund = "das"
mailen(grund, now, temp, humidity, spary)
if wasanderes
grund "wasanderes"
spray =1
mailen(...)
except:
print ('\nFehler: ', exec )
def mailen(grund, now, temp, humidity, spray):
#das ganze mail-gedöns (das Mail-Script ansich, also "solo" geht!)
smtpServer ......
smtpObj.sendmail(,....)
if __name__ == "__main__":
channel = thingspeak.Channel(id=channel_id, api_key=write_key)
while True:
messe(channel)
time.sleep(30)
habe mit (...) abgekürzt
soweit in der Struktur mein Code, den ich aber nur aus den von mir gegoogelten Beispielen zusammen gebaut habe.
Kann ja gut sein, das ich was Grundsätzliche falsch verstanden habe oder falsch anwende.
Die Daten werden wie gewünscht an ThingSpeak übertragen.
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Mittwoch 22. Juni 2022, 11:07
von Sirius3
Eingerückt wird mit 4 Leerzeichen pro Ebene, nicht Tabs.
Um zu wissen, ob Du das Programm verstanden hast, ist es sehr hinderlich, dass Du da kein Python geschrieben hast, sondern irgendwas fragmentarisches.
Nakte excepts darf man nicht benutzten, außer man gibt wirklich den gesamten Traceback aus (z.B. per logging.exception).
Und schließlich: in Deinem ganzen Code kommt kein `exec` vor, so dass man Deinen Fehler auch nicht nachvollziehen kann.
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Mittwoch 22. Juni 2022, 11:17
von bords0
Sirius3 hat geschrieben: Mittwoch 22. Juni 2022, 11:07
Und schließlich: in Deinem ganzen Code kommt kein `exec` vor, so dass man Deinen Fehler auch nicht nachvollziehen kann.
Doch, im print, deshalb wird das ja auch ausgegeben.
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Freitag 24. Juni 2022, 09:00
von Kebap
Was erwartest du von diesen zwei Zeilen?
Ich würde die einfach löschen.
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Freitag 24. Juni 2022, 09:41
von __deets__
Na nicht nur die, sondern auch das try dazu

Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Freitag 24. Juni 2022, 10:03
von Sirius3
In diesem Fall kann es schon sinnvoll sein, alle Exceptions abzufangen, weil es eine Endloschleife geben soll, die bei gelegentlichen Fehlern nicht abgebrochen wird.
Aber dann muß man die Fehlermeldung richtig loggen, und nicht einfach wegwerfen.
So dass das ganze dann so aussieht:
Code: Alles auswählen
import thingspeak
import time
import board
import busio
import smtplib
import sys
import logging
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from adafruit_htu21d import HTU21D
logger = logging.getLogger(__name__)
def messe(channel):
try:
#das ganzemess-gedöhns
if dies:
grund = "das"
mailen(grund, now, temperature, humidity, spray)
if wasanderes:
grund = "wasanderes"
spray = 1
mailen(...)
except:
logger.exception(f'error at messe of channel {channel}')
def mailen(grund, now, temperature, humidity, spray):
#das ganze mail-gedöns (das Mail-Script ansich, also "solo" geht!)
smtp_server = ...
smtp_server.sendmail(...)
def main():
logging.basicConfig()
channel = thingspeak.Channel(id=channel_id, api_key=write_key)
while True:
messe(channel)
time.sleep(30)
if __name__ == "__main__":
main()
Und dann hat man auch alle Informationen, um auf die Fehlersuche gehen zu können.
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Sonntag 26. Juni 2022, 13:06
von dermaxem
OK,
habe das mit dem Logging erweitert und dabei nun festgestellt, das meine Erweiterung des "mailens" um die Variable "now" das Problem darstellt:
Das wollte ich mit dem Umwandeln in "str" beheben, aber irgendwas mache ich falsch:
Hier der Fehler in der "mailen"-Funktion, die u.a. auch "now" mit übergeben bekommet.
Code: Alles auswählen
body = "\n Datum:"+str(now)+"\n\n\nTemperatur:"+temp+"\n\nLuftfeuchts:"+humidity+"\n\nSpray= "+spray
TypeError: can only concatenate str (not "datetime.datetime") to str
das "now" wird weiter oben im code mit
Code: Alles auswählen
from datetime import datetime
now = datetime.now()
spray = 0
bereitgestellt und ist als "global" definiert, so das ich "now" eigentlich von der einen Funktion an die Andere übergeben kann.
-
Nachtrag: Hab es selber gefunden. Ich wandele die VAR vorher selber um mit datetime.now().strftime('%Y-%m-%d %H:%M:%S')
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Sonntag 26. Juni 2022, 13:14
von Sirius3
Bis Du sicher, dass das die Zeile ist, die den Fehler verursacht?
Globale Variablen darf man nicht benutzen, und statt Strings per + zusammenzustückeln, nimmt man Format-Strings, dann hat man auch nicht solche Probleme:
Code: Alles auswählen
body = ("\n
f"Datum: {now}\n\n\n"
f"Temperatur: {temperature}°C\n\n"
f"Luftfeuchte: {humidity}%\n\n"
f"Spray: {spray}"
)
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Sonntag 26. Juni 2022, 13:17
von dermaxem
andere frage dazu:
Wie kann ich die "normale" Ausgabe anzeigen lassen, also die gewollten "print"Ausgaben, die Meldung der Mailen-Funktion aber nicht?
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Sonntag 26. Juni 2022, 13:37
von __deets__
Indem du die print-Funktionen aus dem mailen rausschmeisst? Python kann ja nicht wissen, was es machen soll, wenn du es ihm nicht sagst.
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Sonntag 26. Juni 2022, 13:58
von Sirius3
Dafür gibt es logging, dass verschiedene Funktionen verschiedene Informationen in einer Form ausgeben, dass man danach filtern kann, was man denn eigentlich sehen will.
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Sonntag 26. Juni 2022, 14:25
von dermaxem
Das mit dem "Mailen" klappt nun - ausser das es mir die Konsole voll ballert mit Infos, die ich nicht sehen möchte. Aber es geht nun.
Nun sitze ich am Problem: Rechnen mit Zeiten.
Ich würde gerne 2 Zeiten (now) und (now2) vergleichen und auf eine Differenz von 30 Minuten checken.
Code: Alles auswählen
def zeitvergleich(now):
from datetime import datetime
now2 = datetime.now()
lastcall= now2 - now
if lastcall > 30:
print ("lastcall > 30!") #und dann darf dies und das passieren
print ("lastcall < 30!") #und dann darf eben dies und das nicht passieren
Ich bekomme aber eine Meldung, die mir auch klar ist:
Code: Alles auswählen
if lastspray > 30:
TypeError: '>' not supported between instances of 'datetime.timedelta' and 'int'
da es hier um Zeiten geht, und die "30" ein INT ist, und eben nicht "30 Minuten".
Wie kann man denn mit den Zeiten vergleichen, bzw: wie gebe ich die Vergleichswerte in Minuten an?
Beim googlen finde ich immer nur so Vergleiche mit Time-Delta + 30 Tage und dann die Ausgabe des neuen Datums.
Wie aber kann ich einen Vergleichswert nutzen?
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Sonntag 26. Juni 2022, 14:27
von __deets__
Indem du das mit einem timedelta von 30 Minuten vergleichst.
Re: Neulingsfrage: Variablen bei Script-Aufruf übergeben
Verfasst: Sonntag 26. Juni 2022, 14:34
von dermaxem
Code: Alles auswählen
def zeitvergleich(now):
from datetime import datetime, timedelta
now2 = datetime.now()
lastcall = now2 - now
if lastcall > datetime.timedelta(minutes=30):
print ("JA, ist OK") # also > 30 minunten
print ("neeee.. 30 Minunten sind noch nicht rum"!) # also < 30
da kommt dann aber :
Code: Alles auswählen
AttributeError: type object 'datetime.datetime' has no attribute 'timedelta'