PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : In Python ist es einfach einfache Fehler erst zur laufzeit zu bekommen


SimonX
2018-10-31, 23:29:45
Ich hab schon danach gegoogled, aber ausser py_compile gibts da wohl nichts.

Da python ja ein Script ist, so wie shell scripts, können selbst einfach Tippfehler bei Variablennamen manchmal erst zur Laufzeit erkannt werden.

Als Tips in Netz gibts nur: use linter, test your code.

Beides wird bei uns bereits gemacht (pylint sonarqube und die pycharm ide) und unit-tests so weit wie zeitlich und technisch möglich.

Das ist absolut schwach für Production-Software. Zum Testen muss ich ja sicherstellen, das die code-coverage von jeder method bei über 99% liegt. (womit kann die code-coverage bei python eigentlich checken?) Selbst dann werden die restlichen 1% zur Laufzeit irgendwann mal wegen einer unbekannten variable (wegen typo) fehlschlagen.

Um solch ein Test-Coverage zu bekommen muss man 10x so viel Zeit investieren um das zu erreichen, was ein C/C++ Compiler so nebenbei sicherstellt. (ich habe schon drüber nachgedacht nur zur Build-Zeit alles durch cthyon zu jagen um zu sehen, ob es kompilierbar ist)

Kann hier jemand von seinen Erfahrungen mit Fehlern im Python-Code auf Produktionsmaschinen erzählen und wie diese generell minimiert wurden?


BTW:
Neben dem oben genannten Problem hat Python auch das gleiche Problem wie Java: Keine Konst-Referencen. Man muss also Methoden vertrauen, das Objecte nicht verändert werden, die nicht verändert werden sollen. (besonders dann, wenn die tiefer durchgereicht werden)

Trap
2018-11-01, 00:31:31
Ich bin auch eher in statisch typisierten Sprachen unterwegs, aber ich versuche mal trotzdem eine Argumentation für Python:

Es gibt sehr viele "einfache Fehler" die erst zur Laufzeit sichtbar werden:

typos im sourcecode
null-references
off-by-one
array out of bounds
use after free
invertierte Bedingungen
nicht terminierende Schleifen


Alle davon sind für Produktionssoftware nicht akzeptabel und alle davon kann man durch gute Testabdeckung minimieren.

Ganz nach Donald Knuth "Beware of bugs in the above code; I have only proved it correct, not tried it." ist Code erst dann produktionstauglich wenn man ihn getestet hat.

Die von mir betreute C#-Anwendung hat 40% Blockabdeckung... :tongue:

Ganon
2018-11-01, 10:14:25
Da kann man nur sagen: Willkommen in der Welt der interpretierten, (dyn/non)-typed Sprachen? Da kann man nur sagen: Damit leben und noch mehr Tests schreiben, oder die Sprache wechseln.

Das Problem hat quasi jeder, mit jeder dieser Sprachen. Ob es nun Ruby, JavaScript oder sonst was ist. Von daher gilt auch das, was du da bereits gefunden hast. Lint und Tests.

Python ist aber nicht typlos. Man kann schon vor Benutzung einer Variable auf einen entsprechenden Typ checken. Muss man halt manuell machen. Ich glaube Python 3.5 oder 3.6 hatte sogar optionale Typ-Annotation eingeführt.

Monger
2018-11-01, 10:16:28
Kenne Python jetzt nur vom reviewen, aber die Kritik richtet sich ja allgemein gegen dynamische Sprachen...
Zum einen programmiert man in dynamischen Sprachen anders. In kompilierten Sprachen läuft das ja meist so: Ein paar Zeilen schreiben, kompilieren, Tests laufen lassen.
In dynamischen Sprachen geht das auch, aber um sich erstmal voranzutasten, nutzt man eher sowas wie REPL: https://en.m.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop
Und eine gescheiten Code Editor, weil mit ordentlicher Syntaxprüfung kann man schon sehr viel abfangen, ohne das Schwergewicht eines ganzen Compilevorganges zu brauchen.

C# kennt zwar auch sowas wie Edit & Continue, aber Typen entladen und neu laden ist oft nicht so einfach. Da steig der Debugger bei der ersten Signaturänderung aus.
Das macht dynamische Sprachen super für Prototyping und Einmalcode. Ich schreibe viele kleine Powershell Skripte für kleine Fragestellungen: Wo liegt die Datei mit dem längsten Pfad? In welchen XMLs stehen überall relative Pfade auf X? Wie lange haben die letzten 10 erfolgreichen Builds gedauert? Bis ein C# Entwickler seine Umgebung dafür eingerichtet hat, bin ich längst fertig.

Das zweite große Anwendungsgebiet - und da ist Python besonders gut - sind Sprachübergänge. Jede Programmiersprache hat Grenzen. Python ist super dazu, um Übergänge zwischen unterschiedlichen Systemen und Technologien zu kitten.
Python ist quasi die Metasprache für das Internet der Dinge geworden: Hier ein paar REST services anfragen, miteinander verknüpfen, Anfragen weiterverteilen. Das ist super für Data Science, wo man eh verteilt denkt. Es ist auch super für Datenbanken, wo man eh Daten parsen und validieren muss, was oft nur zur Laufzeit geht. Das ist super wenn man textuellen Inhalt durchsuchen, filtern und interpretieren muss. Das ist gut, wenn du deine UI an die dahinter liegenden Datenquellen binden willst.

Worin dynamische Sprachen nicht gut sind, ist Business Logic. Wenn du sehr breite und komplexe Logikeinheiten ohne Berührpunkte zur Außenwelt hast, ist eine statische Sprache klar im Vorteil.
Aber deshalb mischt man moderne Applikationen ja auch gerne: Backend z.B. in F#, UI in JavaScript oder PHP.

Mosher
2018-11-01, 12:00:17
Kenne Python jetzt nur vom reviewen, aber die Kritik richtet sich ja allgemein gegen dynamische Sprachen...
Zum einen programmiert man in dynamischen Sprachen anders. In kompilierten Sprachen läuft das ja meist so: Ein paar Zeilen schreiben, kompilieren, Tests laufen lassen.
In dynamischen Sprachen geht das auch, aber um sich erstmal voranzutasten, nutzt man eher sowas wie REPL: https://en.m.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop
Und eine gescheiten Code Editor, weil mit ordentlicher Syntaxprüfung kann man schon sehr viel abfangen, ohne das Schwergewicht eines ganzen Compilevorganges zu brauchen.

C# kennt zwar auch sowas wie Edit & Continue, aber Typen entladen und neu laden ist oft nicht so einfach. Da steig der Debugger bei der ersten Signaturänderung aus.
Das macht dynamische Sprachen super für Prototyping und Einmalcode. Ich schreibe viele kleine Powershell Skripte für kleine Fragestellungen: Wo liegt die Datei mit dem längsten Pfad? In welchen XMLs stehen überall relative Pfade auf X? Wie lange haben die letzten 10 erfolgreichen Builds gedauert? Bis ein C# Entwickler seine Umgebung dafür eingerichtet hat, bin ich längst fertig.

Das zweite große Anwendungsgebiet - und da ist Python besonders gut - sind Sprachübergänge. Jede Programmiersprache hat Grenzen. Python ist super dazu, um Übergänge zwischen unterschiedlichen Systemen und Technologien zu kitten.
Python ist quasi die Metasprache für das Internet der Dinge geworden: Hier ein paar REST services anfragen, miteinander verknüpfen, Anfragen weiterverteilen. Das ist super für Data Science, wo man eh verteilt denkt. Es ist auch super für Datenbanken, wo man eh Daten parsen und validieren muss, was oft nur zur Laufzeit geht. Das ist super wenn man textuellen Inhalt durchsuchen, filtern und interpretieren muss. Das ist gut, wenn du deine UI an die dahinter liegenden Datenquellen binden willst.

Worin dynamische Sprachen nicht gut sind, ist Business Logic. Wenn du sehr breite und komplexe Logikeinheiten ohne Berührpunkte zur Außenwelt hast, ist eine statische Sprache klar im Vorteil.
Aber deshalb mischt man moderne Applikationen ja auch gerne: Backend z.B. in F#, UI in JavaScript oder PHP.

Könnte ich alles so unterschreiben

Monger
2018-11-01, 12:05:45
Nachtrag... Könnte evtl hilfreich sein:
https://dmerej.info/blog/post/bye-bye-pylint/

Du hast SonarQube erwähnt. Ich bin kein Fan davon, weil da halt das Kind bereits in den Brunnen gefallen ist.
Linter gehören in ein Build Skript, und das Build Skript in einen Gated Checkin / Merge, damit sowas erst gar nicht in die Codebasis kommt.

Exxtreme
2018-11-01, 13:04:59
Um solch ein Test-Coverage zu bekommen muss man 10x so viel Zeit investieren um das zu erreichen, was ein C/C++ Compiler so nebenbei sicherstellt. (ich habe schon drüber nachgedacht nur zur Build-Zeit alles durch cthyon zu jagen um zu sehen, ob es kompilierbar ist)


Tja, das ist mit ein Grund warum dynamisch typisierte Programmiersprachen nicht skalieren. Für ein 200 LOC-Skript sind sie super weil man hier viel produktiver ist. Geht es aber in Richtung 50k LOC dann kommen die Nachteile so richtig zum Tragen und man ist mit statisch typisierten Sprachen viel produktiver. Weil der Compiler Checks/Tests wegautomatisiert, die man in Python & Co. manuell schreiben muss/sollte.

Und das konstanten Referenzen ist ärgerlich, liesse sich aber zumindest in Java aushebeln mittels Reflection. Eine Garantie hätte man folglich so oder so nicht. Ansonsten bleibt halt der kleine Umweg die Objekte immutable zu machen. Sprich, keine Setter, keine Getter, die die internen Attribute direkt durchreichen und Initialisierung ausschließlich über den Konstruktor.

Monger
2018-11-01, 14:53:01
BTW:
Neben dem oben genannten Problem hat Python auch das gleiche Problem wie Java: Keine Konst-Referencen. Man muss also Methoden vertrauen, das Objecte nicht verändert werden, die nicht verändert werden sollen. (besonders dann, wenn die tiefer durchgereicht werden)
Ich vermute du bist C++ Entwickler?
Dass man die selben Objekte sowohl aufm Stack als auch als Referenz ablegen kann, ist echt ungewöhnlich. Alle modernen Sprachen haben sich das abgewöhnt. Wenn du beides haben willst, also ein Objekt das grundsätzlich modifizierbar ist, aber nicht in diesem Kontext, dann schreib ne Clone Methode. Dann steht es dir frei, beim Aufruf einer Funktion nur ne Kopie mitzugeben.

Marscel
2018-11-01, 20:01:05
Tja, das ist mit ein Grund warum dynamisch typisierte Programmiersprachen nicht skalieren. Für ein 200 LOC-Skript sind sie super weil man hier viel produktiver ist. Geht es aber in Richtung 50k LOC dann kommen die Nachteile so richtig zum Tragen und man ist mit statisch typisierten Sprachen viel produktiver. Weil der Compiler Checks/Tests wegautomatisiert, die man in Python & Co. manuell schreiben muss/sollte.

Das geht schon skalierbar - Aspekte der Performance mal außer Acht gelassen - allerdings ist meine Erfahrung, dass es dafür auch entsprechend erfahrene Entwicklungschefs braucht, die darauf achten, dass entsprechende Code-Richtlinien eingehalten werden.

Aber wenn man selbst bloß mit PHP und Co. großgeworden ist, wer soll dann jemals die Vaterfigur gewesen sein, die einen zu Kohärenz im Voraus nötigt? ;)

SimonX
2018-11-02, 09:13:19
Ich vermute du bist C++ Entwickler?
Dass man die selben Objekte sowohl aufm Stack als auch als Referenz ablegen kann, ist echt ungewöhnlich. Alle modernen Sprachen haben sich das abgewöhnt. Wenn du beides haben willst, also ein Objekt das grundsätzlich modifizierbar ist, aber nicht in diesem Kontext, dann schreib ne Clone Methode. Dann steht es dir frei, beim Aufruf einer Funktion nur ne Kopie mitzugeben.

Es geht hier nicht um den Stack, sondern um objects die für bestimme Benutzer immutable sein sollen und für andere nicht. Z.B. Dictionary in python gibts nicht als immutable.

Auch ein Clone hilft nicht, wenn z.B. der Clone durchgereicht werden muss. Dann steht der Veränderung des Clones nichts im Wege. (Ausser er wäre immutable)

BTW:
Ich schau mir gerade pycodestyle und autopep8 an. Man will ja nicht jedes Blank von Hand tippen müssen.

Monger
2018-11-02, 11:29:30
Auch ein Clone hilft nicht, wenn z.B. der Clone durchgereicht werden muss. Dann steht der Veränderung des Clones nichts im Wege. (Ausser er wäre immutable)

Ja, aber was ist das Problem? Du willst doch die Veränderung des Originals verhindern, oder etwa nicht? Was juckt es dich, wenn Klone verändert werden?

https://stackoverflow.com/questions/2465921/how-to-copy-a-dictionary-and-only-edit-the-copy

Gauß
2018-11-03, 11:35:13
Python usw. ist fuer professionelle Anwendungen extrem unzureichend, da wie von Dir bereits korrekt erkannt, statische Analysewerkzeuge so gut wie nicht existieren und die Leistungseinbussen von ca. zwei Groessenordnungen selbst bei einfachen Dingen wie Textverarbeitung merklich ins Gewicht fallen und eine Ressourcenskallierung nicht moeglich ist.