Sonnenhöhenstand/-azimutberechnung

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
JaquesDuCoudray
User
Beiträge: 4
Registriert: Mittwoch 3. Oktober 2018, 11:29

Hallo zusammen,

bevor ich mich mit meinem Problem an euch wende, möchte ich mich kurz vorstellen.
Ich bin ein Anfänger mit Python, aber nicht im programmieren. Ich möchte Python lernen und habe dafür mein ersten, kleines Projekt entwickelt.
Dieses habe ich bereits vor einigen Jahren in VBA erstellt (wo es auch gute Dienste leistete) und möchte dieses nun in Python übersetzen und nach und nach "aufbohren".
Da ich die Berechnung kenne, fiel darauf meine erste Wahl.

Als erstes möchte ich nur, dass nach der Eingabe des Breiten- und Längengerades alle Sonnenhöhen sowie Azimutstände der Sonne für den jeweilien Standort erfasst werden.
Die Ergebnisse sollen dann mit den korresponiderenen Zeitwerten in einer .txt ausgegeben werden.
Ich denke, das klingt für die meisten von euch ziemlich trivial ;-)

Nun bin ich aber in einen Fehler gerannt, den ich einfach nicht selber beheben kann.
Ich habe den Code mittels einem "Visualizer" Schritt für Schritt getestet und alle Fehler beseitigt. Innerhalb des Visualizer rennt der Code durch und gibt mir die Ergebnisse, die ich möchte.
(Um den Visualizer zu verwenden, habe ich den ganzen .txt-File output code gelöscht und durch print() ersetzt, da es ansonsten nicht unterstütz wird.)
(Der Visualizer ist folgender: pythontutor(dot)com - Dort wird die Version 3.6 unterstützt, ich habe 3.7 auf meinem PC)

Nun mein Problem:
Obwohl er im Visualizer ausführt, führt er unter meinem lokalen Python den Code nicht aus.
Gibt es da einen Versionskonflikt zwischen 3.6 und 3.7?
Ich habe leider so wirklich keine Idee mehr, woran es liegen könnte...

Ich gehe von einer "Kleingkeit" aus, die mir Newbie einfach nicht bewusst ist.
Über Anregungen und Hilfe würde ich mich riesig freuen.

Viele Grüße
Jaques

P.S.: Entschuldigt das blake reinkopieren des Tools, kann man das Script irgendwo hier zur Verfügung stelllen?



Code: Alles auswählen

import math

def f_sonnenhoehe(f_breitengrad, f_laengengrad, f_monat, f_tag, f_stunde, f_minute):
	
	k=math.pi / 180

	tageszahl = (f_monat - 1)*30.3 + f_tag
	deklination = -23.45*math.cos(k*360*(tageszahl+10)/365)
	zeitgleichung_minuten = 60*(-0.171*math.sin(0.0337*tageszahl + 0.465) - 0.1299*math.sin(0.01787*tageszahl  - 0.168))
	stundenwinkel = 15*(f_stunde+f_minute/60-(15-f_laengengrad)/15-12+zeitgleichung_minuten/60)
	sonnenhoehe_sin = math.sin(k*f_breitengrad)*math.sin(k*deklination)+math.cos(k*f_breitengrad)*math.cos(k*deklination)*math.cos(k*stundenwinkel)
	sonnenhoehe_grad = math.asin(sonnenhoehe_sin)/k
	cos_azimut = -(math.sin(k*f_breitengrad)*sonnenhoehe_sin-math.sin(k*deklination))/(math.cos(k*f_breitengrad)*math.sin(math.acos(sonnenhoehe_sin)))
	
	"""Berechnung Sonnenazimut"""
	if f_stunde+f_minute/60 <= 12+(15-f_laengengrad)/15-zeitgleichung_minuten/60 :
		sonnen_azimut = math.acos(cos_azimut)/k
	else :
		sonnen_azimut = 360-math.acos(cos_azimut)/k
	
	return (sonnenhoehe_grad, sonnen_azimut)
	
"""Programmeinführung"""	
print("Dieses Script berechnet für einen Standort die Hoehe und den")
print("Azimut der Sonne für jeden Tag des Jahres")
print("Die Aufloesung ist waehlbar in stuendlich, 15 minuetig, 5 minuetig") """implementierung später"""
print("Die Ergebnisse werden in einer .txt ausgegeben und sind mit Leerzeichen getrennt")
print()
	
print("Eingabe Breitengrad")
breitengrad=int(input("Breitengrad: "))

print("Eingabe Laengengrad")
laengengrad = int(input("Laengengrad: "))




""" Tage 1 bis 365 """
""" Beginnend bei 1 = 01.01. und endet bei 365 = 31.12. """

file=open("sonnenstaende.txt","w")

monat = 0
tag = 0
stunde = 0
minute = 0


while monat <= 12:
	monat += 1
	tag = 0

	while tag <= 30:

		stunde = -1
		tag += 1

		while stunde <= 23:
		
			minute = 0
			stunde += 1

			while minute <= 55:
				sonnenhoehe, sonnenazimut = f_sonnenhoehe(breitengrad, laengengrad, monat, tag, stunde, minute)

				file.write('{:02d}'.format(monat))
				file.write(" ")
				file.write('{:02d}'.format(tag))
				file.write(" ")
				file.write('{:02d}'.format(stunde))
				file.write(" ")
				file.write('{:02d}'.format(minute))
				file.write(" ")
				file.write('{:03d}'.format(sonnenhoehe))
				file.write(" ")
				file.write('{:03d}'.format(sonnenazimut))
				file.write("\n")
				minute += 5 
				
file.close() 

print("Berechnung und Ausgabe in Datei erfolgreich beendet.")
k = input("X für schließen")
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Den Code reinzukopieren ist voellig ok, aber bitte verwende das naechste mal dazu die code-Tags im vollstaendigen Editor. Das ist das Symbol </>. Ich habe das jetzt mal fuer dich nachtraeglich eingefuegt. Wenn man das nicht macht, verliert man die in Python nunmal relevanten Einrueckungen.
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

Es wäre gut, wenn Du die Fehlermeldung posten würdest, die kommt.

Was sollen denn die ganzen f_ bei sonnenhoehe und deren Argumenten?
Strings sind keine Kommentare, die werden mit # eingeleitet.
Statt der while-Schleifen würde man besser for-Schleifen benutzen. Warum hat jeder Monat 31 Tage? Und das Jahr 13 Monate?
Statt der vielen write könnte man das ganze in einem Format-String zusammenfassen.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und jetzt nochmal zu deinem Code:

- was heisst "fuehrt nicht aus"? Gibt es eine Fehlermeldung? Wenn ja, bitte posten. Gibt es ein Verhalten, das nicht ist wie erwartet? Bitte beschreiben.
- in Python rueckt man 4 Leerzeichen ein. Nicht 8. Das wird sonst schnell (so wie bei dir) sehr unuebersichtlich.
- in Python benutzt man keine haendisch zusammengebastelten Zaehler mit while-Schleifen und explizitem Inkrement. Ein simples

Code: Alles auswählen

for monat in range(1, 13):  #Achtung! End-Index exklusive
      ...
reicht.
- du benutzt doch schon """ """ - warum nutzt du es dann nicht gleich, und sparst dir die vielen prints?

Code: Alles auswählen

print("""Dies ist ein Text
der sich ueber mehrere
Zeilen

erstreckt. Und eine {} kommt auch vor""".format("Textersetzung")
- last but not least: statt muehselig zwischen prints und writes zu unterscheiden, nur weil du debugging-Ausgaben auf die Konsole willst, nimm einfach sys.stdout als Datei und schreibe dahin mit writes, oder eben eine geoeffnete Datei:

Code: Alles auswählen

output = sys.stdout
if filename:
     output = open(filename, "w")

....
output.write("foobar\n")
print("text", file=output)
JaquesDuCoudray
User
Beiträge: 4
Registriert: Mittwoch 3. Oktober 2018, 11:29

Hallo zusammen,

habt vielen Dank für die Rückmeldungen und die tollen Anmerkungen.
Beim durchlesen wird mit umso mehr bewusst, dass ich ein totaler Python-Anfänger bin...

@ __deets__
Vielen Dank für das Formatieren. Das werde ich beim nächsten Mal beherzigen.

- Danke Dir für den Hinweis mit den 4 Leerzeichen. Das möchte ich gerne berücksichtigen.
Kannst du mir eine Quelle empfehlen, wo ich solch Community-typische "Absprachen" einsehen kann?

- Danke für den HInweis mit den Schleifen

@ sirius3
- Eine Fehlermeldung erhalte ich nicht. Wenn ich das Script in Python ausführe, öffnet sich kurz das Fenster, schließt sich aber unmittelbar daraufhin wieder.
Was mich wundert, in dem Online-Tool läuft das Script durch und "arbeitet" so, wie ich es mir vorstelle.
Gibt es einen Weg, eine Fehlermeldung zu erzwingen, bzw. das Fenster offen zu halten, auch wenn das Script nicht ausgeführt/abgebrochen wird?

- Die f_ Markierung habe ich von meinen damaligen Vorlesungen aus C++ im Hinterkopf. Als Funktionsname natürlich quatsch.. Aber für die Argumente, um diese als "Membervariablem" (so hiess es damals in C++) zu kennzeichnen.

- Danke für die Aufklärung zu """. ich dachte tatsächlich, dass wären die einleitenden Zeichen für einen Kommentar.

- Ich denke bei den vielen prints() merkt man meine VBA affinität... Format-String ist mir neu, damit werden ich mich auseinander setzen - Danke!

- Die Schleifensteuerung ist noch nicht final, erstmal soll es laufen.

----------------------------------------------
Danke für eure Hinweise.
Die werde ich durchgehen und im Script anpassen. Als Anfänger bin ich dankbar für jeden Hinweis, gerade bei den absoluten Basics, aus denen dieser Code ja mal nur besteht.

Da habe ich noch eine Frage an euch.
Könnt ihr mir eine Quelle empfehlen, wie ich Scripte (z.B. dieses wenn es fertig ist) als .exe "verpacken" kann, so dass es auf Rechner ausgeführt werden kann, die nicht über Python verfügen.
Ist das überhaupt möglich?

Viele Grüße und dankesehr
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Die Hinweise zur Formatierung und anderen Konventionen findest du in PEP8. Einfach mal googeln. Und ein Präfix für member benuzte ich in C++ auch, in Python ist das aber unnötig, weil man bei Objekten ja schon self davor hat. Du nutzt aber eh keine OO im Moment, also sein lassen.

Und was dein Problem angeht: es bietet sich an, das Skript entweder aus einer IDE oder der Shell zu starten. Dann bleiben Ausgaben und Fehlermeldungen stehen. Windows schließt sonst einfach das Fenster ....
JaquesDuCoudray
User
Beiträge: 4
Registriert: Mittwoch 3. Oktober 2018, 11:29

Hi __deets__,

danke für deine Antwort.
Das war ein blutiger Anfängerfehler, ich habe das Script nicht so gestartet, wie man es tun sollte... Ergo, kein Debugging etc.

Der Debugger hat mir einen Fehler in Zeile
file.write('{:03d}'.format(sonnenhoehe))
gegeben mit dem Hinweis, dass ein float dieses Format nicht unterstützt. Es macht auch keinen Sinn, so weit habe ich nicht gedacht.

Nun läuft das Script durch und macht was es soll. Super! :-) Danke euch für die Hilfe und die Anregungen, welche dazu nötig waren.

Könnt ihr mir bitte noch einen Hinweis darauf geben, wie und ob man Scripte in .exe bekommt?
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das geht mit pyinstaller oder py2exe. Und ggf auch cx_freeze.
JaquesDuCoudray
User
Beiträge: 4
Registriert: Mittwoch 3. Oktober 2018, 11:29

Top, danke Dir!
Antworten