Wie sieht kommerzielle Pythonentwicklung aus?
Ich hab eine Konsoleanwendung geschrieben, die zusammgehackt ist.
Sie parst Argumente, ließt Dateien ein, baut ein Model, ruft externe Optimierungsoftware auf, und schreibt das Ergebnis in eine Datei und kann Plots erstellen.
Im moment hab ich Pycharm für den Debugger benutzt.
Die Anwendung wird bald sehr viel weiter ausgebaut.
Ich möchte jetzt das ganze Professioneller angehen und wollte euch fragen wie das geht.
Ich möchte einen Debugger, Versionskontrolle, einen Profiler, einen automatisierten Test und was sonst auch noch immer dazugehört.
Was bietet sich da an?
Desweitern wäre interessant wie man eine Konsoleanwendung am besten struktiert? Gibt es dafür Vorlagen?
Ich möchte am Ende eine Projekt haben, das leicht auf Fehler zu untersuchen ist.
Vielen Dank!
Professionelle Python Entwicklung
Mit Pycharm bist du schon recht weit in der Liste der Debugger fortgeschritten... Vielleicht Visual Studio (gibt dafür relativ viele Addons, auch was Python angeht) ? Das kostet halt (ausser du nimmst Express )
Was die zweite Frage angeht: Was ist mit strukturieren gemeint ?
Was die zweite Frage angeht: Was ist mit strukturieren gemeint ?
-> optparsenvidia11 hat geschrieben:Sie parst Argumente
versuche bei numerischen Daten soweit wie möglich auf Schleifen zu verzichten -> numpy.loadtxtnvidia11 hat geschrieben:ließt Dateien
versuche zur externen Software eine Python-Schnittstelle zu bauen (z.B. mit Swig)nvidia11 hat geschrieben:ruft externe Optimierungsoftware auf
als Text oder Binär? Wenn binär nimm hdf5nvidia11 hat geschrieben:schreibt das Ergebnis in eine Datei
Eclipse mit Pydev und Subclipse kann das.nvidia11 hat geschrieben:Ich möchte einen Debugger, Versionskontrolle, einen Profiler, einen automatisierten Test und was sonst auch noch immer dazugehört.
Beim Repository (Versionskontrolle) überleg ob ein Zentrales (Subversion) oder ein Dezentrales (Git) besser für Dich geeignet ist.
Das Konzept einer Konsolenanwendung, die in der Main-Funktion erstmal eine Ini-Datei parst, ist für kompilierte Sprachen oftmals ein notwendiges Übel. Flexibilität wird durch immer komplexere Ini-Daten Strukturen realisiert, bis man bald seine eigene Ini-Datei-Skript-Sprache entwickelt hat.nvidia11 hat geschrieben:Desweitern wäre interessant wie man eine Konsoleanwendung am besten struktiert?
In Python hast Du dafür ganz andere Möglichkeiten. Schreib Deine Anwendung als Bibliothek. Anstatt Ini-Dateien schreibst Du kleine Python-Start-Skripte, die die Parameter an die Objekte der Bibliothek übergeben.
@nvidia11: Wenn Du mit "zusammengehackt" meinst, dass sie keine innere Struktur hat, nicht in Funktionen aufgeteilt ist, usw. dann ist das doch schon ein guter Startpunkt für Verbesserungen. Die grobe Struktur einer Konsolenanwendung hast Du ja schon beschrieben: Argumente parsen, Datenstrukturen für die Rechnung aufbauen, rechnen, Ergebnis ausgeben. Wenn das alles nach Aufgaben getrennt in Funktionen, die für sich nicht zu komplex sind, gegliedert ist und für jede Funktion Unit-Tests geschrieben sind und es für die ganze Anwendung auch noch Testdatensätze gibt, dann bist Du schon recht weit, dass Du ohne große Sorgen die Anwendung auch weiter ausbauen kannst. Ein Versionskontrollsystem ist übrigens von der ersten Zeile an sinnvoll.
@MagBen: optparse ist veraltet, argparse ist aktuell.
Der Rest Deiner Anmerkungen hängt wohl stark davon ab, was gemacht wird, und wie die Schnittstellen aussehen.
Auch Pycharm hat Debugger, Versionskontrolle und Profiler, unterscheidet sich also von Eclipse in diesen Punkten nicht.
Von ini-Dateien ist auch gar nicht die Rede.
@MagBen: optparse ist veraltet, argparse ist aktuell.
Der Rest Deiner Anmerkungen hängt wohl stark davon ab, was gemacht wird, und wie die Schnittstellen aussehen.
Auch Pycharm hat Debugger, Versionskontrolle und Profiler, unterscheidet sich also von Eclipse in diesen Punkten nicht.
Von ini-Dateien ist auch gar nicht die Rede.
Wenn Swig als Anbindung zur Fremdsoftware benutzt wird, dann hat man als Abhängigkeit ja direkt einen C- oder C++-Compiler. Dies würde ich dem Nutzer eines in Python geschriebenen Shell-Tools eigentlich nach Möglichkeit ersparen wollen und daher eher nicht empfehlen. Außer natürlich, es geht nicht anders, d.h. dass der direkte Bibliothekszugriff zwingend erforderlich ist und dass ``ctypes`` ausscheidet.MagBen hat geschrieben:versuche zur externen Software eine Python-Schnittstelle zu bauen (z.B. mit Swig)nvidia11 hat geschrieben:ruft externe Optimierungsoftware auf
Wohlgemerkt wurden hier überhaupt keine Angaben dazu gemacht, in welcher Sprache das externe Programm geschrieben wurde bzw ob es eine Bibliothek zur Verfügung stellt.
@nvidia11: Neben den Modulen in der Standardbibliothek zur Auswertung von Optionen und Argumenten von der Kommandozeile gibt es noch Alternativen. `click` macht zum Beispiel einen interessanten Eindruck um Konsolenanwendungen mit einer API auszustatten die ”Kommandos” auf Funktionen abbildet und dabei einfach erweiter- und kombinierbar ist.
Versionskontrolle: Git oder Mercurial sind da wohl im Moment die am meisten verwendeten.
Für automatisierte Tests gibt es `unittest` in der Standardbibliothek, aber auch Lösungen wie `nose` oder `py.test` die weniger wie Java daher kommen und eine einfacherere API bieten um Tests zu schreiben.
Versionskontrolle: Git oder Mercurial sind da wohl im Moment die am meisten verwendeten.
Für automatisierte Tests gibt es `unittest` in der Standardbibliothek, aber auch Lösungen wie `nose` oder `py.test` die weniger wie Java daher kommen und eine einfacherere API bieten um Tests zu schreiben.
Vielen Dank für die Antworten!
Also ja bis jetzt ist es ein Skript ohne irgendeine Funktion.
Mein Vorgehen:
Ich führe eine main-methode ein und dann für jedes beschriebene Teilgebiet eine eigene Funktion.
1) click sieht sehr gut aus! Ich hätte vorgeschlagen, da es sehr viele Parameter sind und alle Voreinstellungen haben,
das ich alle als globale Variablen am Anfang deklariere und in meiner parseArg()-Funktion dann alle gegebenen überschreibe.
2) Beim Einlesen. Ich erstelle auch die Dateien, die ich einlese mit einem anderen Tool das auch in python geschrieben ist. Die Dateien sind einfache Textdateien, die wie eine Art Baum aufgebaut sind. Da bietet sich wahrscheinlich XML am besten an? Meine Datenstrukturen sehen so aus:
Also self.Trains enthält eine Liste von Trains und Trains enthält eine Liste von RouteTrains.
3) Die Optimierungssoftware ist eine Pythonbiblothek. Aber es wird bald eine andere mit dazu genommen, die in C++ geschrieben ist und für die es keinen Pythonwrapper gibt. Ist das viel Aufwand die Datenstrukturen an C++ zu übergeben?
4) Hat PyCharm einen Profiler? ich hab nichts dazu gefunden. Eine Versionsverwaltung kann man integrieren, das sieht gut aus.
Also ja bis jetzt ist es ein Skript ohne irgendeine Funktion.
Mein Vorgehen:
Ich führe eine main-methode ein und dann für jedes beschriebene Teilgebiet eine eigene Funktion.
1) click sieht sehr gut aus! Ich hätte vorgeschlagen, da es sehr viele Parameter sind und alle Voreinstellungen haben,
das ich alle als globale Variablen am Anfang deklariere und in meiner parseArg()-Funktion dann alle gegebenen überschreibe.
2) Beim Einlesen. Ich erstelle auch die Dateien, die ich einlese mit einem anderen Tool das auch in python geschrieben ist. Die Dateien sind einfache Textdateien, die wie eine Art Baum aufgebaut sind. Da bietet sich wahrscheinlich XML am besten an? Meine Datenstrukturen sehen so aus:
Code: Alles auswählen
class _TrainSystem:
def __init__(self, intervall, numbertrains, Trains):
self.intervall = intervall
self.numbertrains = numbertrains
self.Trains = Trains
class _Train:
def __init__(self, trainnr, RouteTrains):
self.trainnr = trainnr
self.RouteTrains = RouteTrains
class _RouteTrain:
sol = -1 # Abfahrt in der Lösung
def __init__(self, route, time, dwell, early, late, depart, pos, dis, power):
self.route = route # Strecke
self.time = time # Fahrzeit
self.dwell = dwell # Wartezeit
self.early = early # Früheste Abfraht
self.late = late # Späteste Abfahrt
self.depart = depart # Bisherige Abfahrt
self.pos = pos # Reihenfolgenummer auf der Strecke
self.dis = dis # Mindestabstand des nächsten Zuges
self.power = power # Leistungsprofil
3) Die Optimierungssoftware ist eine Pythonbiblothek. Aber es wird bald eine andere mit dazu genommen, die in C++ geschrieben ist und für die es keinen Pythonwrapper gibt. Ist das viel Aufwand die Datenstrukturen an C++ zu übergeben?
4) Hat PyCharm einen Profiler? ich hab nichts dazu gefunden. Eine Versionsverwaltung kann man integrieren, das sieht gut aus.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
@1: Globale Variablen sind fast nie der Weg zu Ziel
Übergib die Parameter oder kreiere ein Valueobjekt, welches eine Menge von Werten bündelt und übergebe dieses.
@2: Es gibt eine Menge (andere) Formate, die man nutzen könnte... JSON wäre z.B. etwas. Aber XML geht natürlich auch. Deine Namen sehen komisch aus. Wieso so viele Abkürzungen? Und wozu die hässlichen Unterstriche als Präfix der Klassen? Attribute werden laut PEP8 klein geschrieben.
@3: Das kommt prinzipiell darauf an
Hat die C++-Schnittstelle denn ein bestimmtes Format, welches sie akzeptiert? Wenn ja, könnte es sinnvoll sein, die Persistenz bereits jetzt darauf auszulegen.

@2: Es gibt eine Menge (andere) Formate, die man nutzen könnte... JSON wäre z.B. etwas. Aber XML geht natürlich auch. Deine Namen sehen komisch aus. Wieso so viele Abkürzungen? Und wozu die hässlichen Unterstriche als Präfix der Klassen? Attribute werden laut PEP8 klein geschrieben.
@3: Das kommt prinzipiell darauf an

encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
@1 ok also keine globalen Variablen 
Wann sind denn globale Variablen sinnvoll?
@2 ich war zu faul immer das ab zu tippen, die _ Striche damit ich das Objekt von der Klasse nochmal ohne den _ erzeugen kann mit dem gleichen Namen
Ja xml dachte ich mir, weil man es dann auch mal anschauen kann und noch was lesen kann.
@3 Das hier ist die Bibliothek
http://www.localsolver.com/solvingyourf ... incpp.html
Im Prinzip hab ich das Bauen des Models schon in Python geschrieben halt für einen anderen Löser, der eine Pythonapi hat.
Der hat jetzt keine python api, d.h. ich müsste die Datenstrukturen an C++ übergeben und dann dort Model bauen.

Wann sind denn globale Variablen sinnvoll?
@2 ich war zu faul immer das ab zu tippen, die _ Striche damit ich das Objekt von der Klasse nochmal ohne den _ erzeugen kann mit dem gleichen Namen
Ja xml dachte ich mir, weil man es dann auch mal anschauen kann und noch was lesen kann.
@3 Das hier ist die Bibliothek
http://www.localsolver.com/solvingyourf ... incpp.html
Im Prinzip hab ich das Bauen des Models schon in Python geschrieben halt für einen anderen Löser, der eine Pythonapi hat.
Der hat jetzt keine python api, d.h. ich müsste die Datenstrukturen an C++ übergeben und dann dort Model bauen.
Wenn Du es mit Swig machst, dann würdest Du Swig mitteilen, dass für localsolver.h ein Python-Wrapper erstellt werden soll. Wenn das klappt (d.h. localsolver.h nichts enthält womit Swig nicht zurechkommt), dann kannst Du die main Funktion von http://www.localsolver.com/solvingyourf ... incpp.html eins-zu-eins in Python Code übertragen.nvidia11 hat geschrieben:Ist das viel Aufwand die Datenstrukturen an C++ zu übergeben?
@nvidia11: @1 Eigentlich niemals.
@2: Da nur Klassennamen mit einem Grossbuchtaben anfangen und Konstanten durchgehend in Grossbuchstaben geschrieben werden, ist das mit dem Unterstrich nicht sinnvoll. Lesestoff: Style Guide for Python Code. Die übliche Einrücktiefe ist übrigens vier Leerzeichen pro Ebene.
JSON kann man auch in einem Texteditor öffnen und lesen.
@2: Da nur Klassennamen mit einem Grossbuchtaben anfangen und Konstanten durchgehend in Grossbuchstaben geschrieben werden, ist das mit dem Unterstrich nicht sinnvoll. Lesestoff: Style Guide for Python Code. Die übliche Einrücktiefe ist übrigens vier Leerzeichen pro Ebene.
JSON kann man auch in einem Texteditor öffnen und lesen.