Seite 1 von 1
Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 08:21
von Patricia
Hallo zusammen
Ich habe einen Code, den ich in Einzelschritten in Jupyter getestet habe und der klappt.
Nun möchte ich das Ganze zu einer Funktion zusammenfassen und mit xlwings dann in Excel laufen lassen.
Jedoch erhalte ich hier nun einen SyntaxError Fehler in Zeile 12 "invalid syntax" (bei "zählerstand.drop...)
Wenn ich zB diesen Schritt mit #glatt stelle, dann kommt der gleiche Fehler in Zeile 13, dann in 14 etc.
Habe das Gefühl, als ob der Code hier in der Funktion zusammengefasst die Einzelschritte nicht ausgibt.
Oder an was könnte es sonst liegen? Hätte evtl. jemand eine Idee?
Code: Alles auswählen
import requests
import pandas as pd
import xlwings as xw
def values_in_past_multiple(deviceId, startdate, enddate):
interval = int(1000)
base_url = 'https://smart-me.com:443/api/ValuesinPastMultiple'
auth_data = ('xx', 'xx')
response = requests.get(f'{base_url}/{deviceId}?startDate={startdate}, &endDate={enddate}&interval={interval}', auth=auth_data)
response.raise_for_status()
zählerstand = response.json()
zählerstand = pd.DataFrame(zählerstand)
zählerstand['Date'] = pd.to_datetime(zählerstand['Date'].dt.tz_localize(False)
zählerstand.drop('Values', axis=1, inplace=True)
zählerstand['Values'].apply(pd.Series)[0].apply(pd.Series).drop(columns='Obis')
zählerstand3 = pd.concat([zählerstand1, zählerstand2], axis=1)
zählerstand3['Value']=zählerstand['Value'].astype(int)
zählerstand3 = zählerstand2.pivot(index=['Date'], columns=['DeviceId'])
return zählerstand3
Danke
Patricia
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 08:24
von pillmuncher
Zähl mal in der Zeile darüber, wieviele öffnende und schließende Klammern da stehen. Tipp: Beide Zahlen müssen gleich sein.
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 08:47
von __blackjack__
@Patricia: Anmerkungen zum Quelltext: ``int(1000)`` macht keinen Sinn. 1000 ist bereits eine ganze Zahl, die wird durch das `int()` nicht irgendwie ”ganzzahliger”.
Die Parameter würde ich `requests` zusammenbasteln lassen. Das ist übersichtlicher und robuster. Das Komma und das Leerzeichen dürften auch falsch sein.
Namen sollten innerhalb des gleichen Namensraums nicht an Werte mit unterschiedlichen (Duck-)Typen gebunden werden. Also nicht den gleichen Namen an JSON-Daten und `DataFrame`-Objekte. Man muss auch nicht jedes Zwischenergebnis an einen Namen binden.
Man sollte keine Namen nummerieren und `zählerstand1` und `zählerstand2` werden auch gar nicht definiert.
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 10:14
von Patricia
@pillmuncher: Danke - copy paste Fehler!
@blackack:
Was meinst du mit "requests zusammenbasteln"?
Ich habe den code nun erstellt, und er läuft soweit, ausser dass er die Spalte, welche einen dictionary enthält, nicht mehr anpasst.
Was ich versuchen wollte, und im Jupityer Einzelschritt funktioniert das auch, ist folgendes:
Ich habe die Spalte "Values". Diese sieht so aus - enthält also einen Dictionary:
[{'Obis': '1-0.1.8....', 'Value": "3954..."{]
Nun möchte ich von dieser Spalte lediglichen den Wert aus dem Value auslesen, also im Beispiel hier zB 3954...
Im Jupyter mit Einzelschritten hat das mit diesem Code funktioniert:
Code: Alles auswählen
zählerstand['Values'].apply(pd.Series)[0].apply(pd.Series).drop(columns='Obis')
Aber in der Funktion geht das nicht, ich erhalte als Ausgabe immer noch die Spalte mit den Dictionary Werten.
Hier nochmals mein abgeänderter Code:
Code: Alles auswählen
@xw.func
#@xw.arg("deviceId", expand = "right")
@xw.ret(index = True, header = True)
def values_in_past_multiple(deviceId, startdate, enddate):
interval = 1000
base_url = 'https://smart-me.com:443/api/ValuesinPastMultiple'
auth_data = ('xx', 'xx')
response = requests.get(f'{base_url}/{deviceId}?startDate={startdate}&endDate={enddate}&interval={interval}',auth=auth_data)
response.raise_for_status()
zählerstand = response.json()
zählerstand = pd.DataFrame(zählerstand)
zählerstand['Date'] = pd.to_datetime(zählerstand['Date'])
zählerstand['Date'] = zählerstand['Date'].dt.tz_localize(None)
zählerstand['Values'].apply(pd.Series)[0].apply(pd.Series).drop(columns='Obis')
#zählerstand.drop('Values', axis=1, inplace=True)
#zählerstand3 = pd.concat([zählerstand1, zählerstand2], axis=1)
#zählerstand['Value']=zählerstand['Value'].astype(int)
zählerstand = zählerstand.pivot(index=['Date'], columns=['DeviceId'])
return zählerstand
An was könnte das nun wieder liegen?
Danke für deine Hilfe!
Patricia
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 10:21
von __deets__
Das Modul requests erlaubt dir, Parameter als Woerterbuch zu uebergeben, und sorgt dann dafuer, dass die HTTP-konform verschickt werden. Du machst das hingegen selbst, und das auch noch mit Fehlern darin, wie zB dem Leerzeichen vor &endDate.
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 10:52
von einfachTobi
Ich vermute, dass du die Umformung komplizierter machst als es sein müsste. Kannst du mal als Beispiel eine vollständige Antwort der API (JSON) posten und wie das Endergebnis aussehen soll?
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 11:39
von __blackjack__
Ich würde die Umformung einfach in Python vornehmen. Ungetestet:
Code: Alles auswählen
@xw.func
# @xw.arg("device_id", expand="right")
@xw.ret(index=True, header=True)
def values_in_past_multiple(device_id, start_date, end_date):
url = "https://smart-me.com/api/ValuesinPastMultiple"
response = requests.get(
f"{url}/{device_id}",
params={
"startDate": start_date,
"endDate": end_date,
"interval": "1000",
},
auth=("xx", "xx"),
timeout=None,
)
response.raise_for_status()
return pd.DataFrame.from_records(
[
{
"Date": pd.to_datetime(record["Date"]).tz_localize(None),
**{item["Obis"]: item["Value"] for item in record["Values"]},
}
for record in response.json()
]
)
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 12:21
von Patricia
@deets: es ist eine API Abfrage und ich muss doch im request genau angeben, was ich abfragen möchte? Die Leerzeichen habe ich nun entfernt, hatte aber keinen Einfluss.
https://smart-me.com/swagger/ui/index#! ... ltiple_Get
@Tobi
Ich hoffe das klappt so mit der Anzeige des Bildes?
So sieht die Tabelle aus mit der aktuellen Abfrage:
https://i.imgur.com/LZVvK5H.png
So sieht die Tabelle aus wenn ich es in Einzelschritten in Jupyter habe laufen lassen - und das wäre auch mein gewünschter output.
https://i.imgur.com/MQjFRvB.png
Wenn ich den Code umschreibe so wie blackjack ihn mir eben gesandt hat, sieht das Resultat so aus:
Code: Alles auswählen
@xw.func
# @xw.arg("device_id", expand="right")
@xw.ret(index=True, header=True)
def values_in_past_multiple(device_id, start_date, end_date):
url = "https://smart-me.com/api/ValuesinPastMultiple"
response = requests.get(
f"{url}/{device_id}",
params={
"startDate": start_date,
"endDate": end_date,
"interval": "1000",
},
auth=(email.ch", " passwott"),
timeout=None,
)
response.raise_for_status()
return pd.DataFrame.from_records(
[
{
"Date": pd.to_datetime(record["Date"]).tz_localize(None),
**{item["Obis"]: item["Value"] for item in record["Values"]},
}
for record in response.json()
]
)
https://i.imgur.com/9pQWOL4.png
..bin etwas verloren Leute..
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 12:49
von __deets__
Ich habe mal sehr schnell die Auth-Daten geändert. Die hattest du im
Klartext da stehen. Besser ändern.
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 12:56
von __blackjack__
@Patricia: Welchen von den Obis-Werten hast Du denn in Deinem Wunschergebnis genommen? Oder sind die etwa alle in einer Spalte ohne die Information was die Zahl denn nun eigentlich bedeutet? Oder hast Du irgendwo in Deinem Code einen einzigen Obis-Wert heraus gepickt? Anhand eines Indexwertes? Sicher, dass der garantiert ist? Denn die Werte haben ja nicht ohne Grund eine Obis-ID um sie zu idenzifizieren. *Die* sollte dann auch beim Selektieren angewendet werden.
Eine Spalte in der für jeden Wert immer die gleiche Geräte-ID steht, kann man bei meinem Code leicht ergänzen, aber warum? Die ist doch für alle Werte gleich‽
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 13:42
von Patricia
Ich möchte jeweils nur den ersten Obis Wert..
https://i.imgur.com/XGk03UP.png
Ich verstehe einfach nicht, weshalb das im Einzelschritt funktioniert und mit der Funktion nicht..
Wenn ich es in Excel auslesen mit den Einzelschritten, erhalte ich auch das richtige Resultat!
https://i.imgur.com/7IQGrhs.png
Ich möchte dann am Ende eine Liste, wo viele verschiedene Geräte ID's abgefragt werden.
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 14:49
von Sirius3
Dann mußt Du doch nur nach dem richtigen Obis-Wert filtern:
Code: Alles auswählen
@xw.func
# @xw.arg("device_id", expand="right")
@xw.ret(index=True, header=True)
def values_in_past_multiple(device_id, start_date, end_date):
url = "https://smart-me.com/api/ValuesinPastMultiple"
response = requests.get(
f"{url}/{device_id}",
params={
"startDate": start_date,
"endDate": end_date,
"interval": "1000",
},
auth=("xx", "xx"),
timeout=None,
)
response.raise_for_status()
return pd.DataFrame.from_records(
[
(
pd.to_datetime(record["Date"]).tz_localize(None),
next(item["Value"] for item in record["Values"] if item["Obis"] == "1-0:1.8.0*255"),
) for record in response.json()
], columns=['date', value']
)
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 14:54
von __blackjack__
@Patricia: Wenn Du den ersten Obis-Wert aus der Übersichtstabelle willst, dann ist Dein bisheriges Ergebnis nur zufällig richtig, denn Du nimmst den zweiten Obis-Wert, der offenbar immer den gleichen Wert wie der erste Obis-Wert hat.
Ungetestet:
Code: Alles auswählen
@xw.func
# @xw.arg("device_id", expand="right")
@xw.ret(index=True, header=True)
def values_in_past_multiple(device_id, start_date, end_date):
url = "https://smart-me.com/api/ValuesinPastMultiple"
response = requests.get(
f"{url}/{device_id}",
params={
"startDate": start_date,
"endDate": end_date,
"interval": "1000",
},
auth=("xxx", "xxx"),
timeout=None,
)
response.raise_for_status()
return pd.DataFrame.from_records(
[
{
"DeviceId": device_id,
"Date": pd.to_datetime(record["Date"]).tz_localize(None),
"Value": next(
item["Value"]
for item in record["Values"]
if item["Obis"] == "1-0:1.8.0*255"
),
}
for record in response.json()
]
)
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 15:10
von Patricia
@Sirius3
Bingo!! Nun klappt es!!
Puh aber das hätte ich alleine nie rausgekriegt!!
https://i.imgur.com/i47JoPH.png
Schade nur dass ich keine Abfrage mit kürzeren Intervallen machen kann. Die API erlaubt das nicht. Denn die Werte werden eigentlich alle 15 Min abgelesen.
VIELEN DANK!!!!
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 15:40
von einfachTobi
Die API erlaubt auch kürzere Intervalle. Die von dir gepostete Doku sagt: The interval in minutes betwenn the values. 0 means as fast as possible. Only 1000 values can be get in one call.. Du musst dann lediglich den Zeitraum kleiner wählen, damit die 1000 Werte mit dem gewünschten Intervall da rein passen.
Re: Funktion/Code läuft nicht durch/Syntax error
Verfasst: Mittwoch 28. September 2022, 19:11
von Patricia
@Tobi
Danke dir auch für diese Rückmeldung!
Ich brauche diese Werte für die Abrechnung der Energiebezüge und diese sind jeweils 6 Monate und ich würde es gerne auch grafisch darstellen. D.h. ich muss da wohl mehr als eine Abfrage machen und diese dann zusammenfügen... bleibt mir noch einiges zu tun:-)!
Beste Grüsse
Patricia