@cz3kit: Und was passiert wenn Du das so eingibst? Fehlermeldung? Gar nichts? Woher weisst Du, dass es an `optparse` liegt? Was wird ausgeführt? Wo bricht die Ausführung ab? Was hast Du unternommen um das herauszufinden?
Das diese Klasse einen schlechten Namen hat und sinnlos ist, darüber kann man nicht streiten. Die Aufgabe wird sicher nicht gewesen sein das nur in eine Klasse zu stecken, sondern eine Klassen *sinnvoll* zu verwenden. Was sind denn hier die gemeinsamen Daten, auf denen die Methoden operieren? Und warum bindest Du so ziemlich alles als Attribut an das Objekt?
Was sollen die Kommentare mit den '-'-Linien die nur den folgenden Funktionsnamen enthalten? Das ist sinnlose Redundanz. Kommentare sollen dem Leser etwas sagen, was er nicht sowieso aus dem Quelltext schon problemlos ersehen kann.
In einer `__init__()`-Methode sollte ein Objekt initialisiert werden, so dass es danach in einem benutzbaren Zustand ist. Per Konvention sollten dort auch alle Attribute auf dem Objekt mit sinnvollen Werten belegt werden. Attribute, die erst in anderen Methoden eingeführt werden, machen Programme fehleranfälliger und schwerer zu lesen und zu verstehen, weil man nicht an einer Stelle sieht, welche Attribute es gibt, und die Existenz von Attributen von der Reihenfolge der Methodenaufrufe zur Laufzeit abhängt. Der Docstring der `__init__()` sagt nichts aus, was man ohne ihn nicht wüsste -- weg damit. Für Docstrings gilt dasselbe wie für Kommentare.
`RLed.quiet` ist ein Wahrheitswert, dafür sollte man nicht 0 und 1 missbrauchen, wo es `True` und `False` extra dafür gibt. Das Attribut wird weder inner- noch ausserhalb der Klasse verwendet, kann also weg.
Argumente sollte man nur `*file` nennen, wenn dort wirklich ein datei-ähnliches Objekt erwartet wird, bei dir werden aber keinen Dateien, sondern Datei*namen* erwartet.
Deine Ausnahmebehandlung ist durch die Bank weg unsinnig. Wenn Du sie da nicht hättest, würde Dir auch der Grund der Ausnahme ausgegeben. Und vor allem machst Du nach der Ausnahmebehandlung einfach mit der jeweiligen Operation weiter als wenn nichts gewesen wäre. Wenn ein `open()` mit einer Ausnahme fehlschlägt, macht es ja wohl nicht viel Sinn danach aus so einer nicht geöffneten Datei etwas zu lesen oder etwas hineinzuschreiben. Da kommt unweigerlich die nächste Ausnahme, die Du dann aber gar nicht behandelst. Der Benutzer bekommt also auf jeden Fall eine unbehandelte Ausnahme samt Stacktrace zu sehen, trotz Deiner "Ausnahmebehandlungen".
Namen komplett in GROSSBUCHSTABEN sind für Konstanten vorgesehen und Konstanten definiert man nicht bei jedem Funktionsaufruf und in verschiedenen Funktionen immer neu, sondern *einmal* innerhalb eines Programmlaufs, entweder auf Modulebene, oder zum Beispiel als Klassenattribut.
Und dann sollte man so eine Konstante auch konsequent *benutzen* und nicht über den ganzen Quelltext verstreut einen konstanten Wert doch wieder als literale "magische" Zahl schreiben. Und das auch noch mal in hexadezimaler und mal in dezimaler Schreibweise. Wer soll denn da den Überblick behalten. Wenn Du das mal von 0x90 auf etwas anderes umstellen möchtest, dann sollte der Quelltext so gestaltet sein, dass man den Wert an *genau einer Stelle* im Programm verändern muss. Sonst besteht die Gefahr, dass man bei so einer Änderung eine der vielen Stellen übersieht und das Programm dann defekt ist.
Warum ist der Docstring bei `expand()` auskommentiert?
`i` ist kein Name, den man für Zeichenketten verwenden sollte. Das ist ein typischer Name für eine "Zählvariable" bei der Programmierer eine ganze Zahl als Typ erwarten. Was da in `expand()` in der Schleife veranstaltet wird, ist alles andere als selbsterklärend. Da wäre ein Kommentar angebracht.
Explizite Vergleiche von Wahrheitswerten auf ``== True`` oder ``== False`` sind überlüssig und schlechter Stil. `os.path.isfile()` liefert schon einen Wahrheitswert, den braucht man nicht noch einmal mit `True` vergleichen, nur um wieder genau den gleichen Wahrheitswert zu erhalten.
Zum Trennen von Dateinamen und Erweiterung gibt es `os.path.splitext()`. Deine Methode fällt auf die Nase, wenn im Namen mehr als ein '.' enthalten ist.
In der Funktion wird der Ausgabedateiname an mehreren Stellen aufs Neue zusammengesetzt. Das kann man auch *einmal* machen, bevor man ihn das erste mal benötigt.
Die Funktion vermischt Programmfunktionalität mit Benutzerinteraktion, ist also nicht gut wiederverwendbar. Auch sollten Funtkionen nicht einfach mit `sys.exit()` das komplette Programm beenden. Das sollte einem sehr kleinen Programmteil vorbehalten bleiben, der ganz weit oben in der Aufrufhierarchie steht.
Die Namen `rled` und `bitmap` sind schlecht gewählt. Was soll ein `rled` sein? Ist das ein Kunstwort? Eine Abkürzung? `bitmap` ist schlecht gewählt, weil es viel zu einschränkend ist. Das ist ein allgemeiner Kompressionsalgorithmus, der funktioniert nicht nur mit Grafikdaten.
Was soll der Kommentar in Zeile 136? Ist das auskommentierter Quelltext? Dann weg damit. Soll das sagen, dass `self.num` eigentlich `self.number` heissen sollte? Dann umbenennen und weg mit dem Kommentar.
Das Dateiformat ist ungünstig aufgebaut. Erst sollten die Teile kommen, von denen die Länge in Bytes bekannt ist, also die Kennung und die Kompressionsart. Und dann erst die in der Länge variable Dateinamenserweiterung. Dann würde das Programm einfacher werden. Auch sollte die Kennung als Konstante definiert werden und nicht mehrfach im Quelltext als Zeichenkettenliteral auftauchen.
Das Dateiformat kommt übrigens nicht mit allen Dateinamen klar. Welche komplett ohne Endung und solche wo ein '>' in der Endung vorkommt, funktionieren mit dem Format nicht. Ersteres ist bei Textdateien gar nicht so selten.
In `compress_simple()` werden die Eingabedaten nicht überprüft. Das Programm sollte auch vernünftig reagieren, wenn der Benutzer eine Datei angibt, die nicht nur Bytewerte zwischen 0 und 127 enthält. So etwas machen Benutzer nämlich gerne -- sich nicht an die Anleitung halten. Sofern sie die überhaupt gelesen haben.
Einige Namen halten sich nicht an PEP8. Insbesondere mischt Du den empfohlenen Stil mit mixedCase. Man kann's ja gerne "falsch" machen, dann aber doch bitte konsequent.
`getCoding()` braucht Dokumentation und/oder einen besseren Namen. Ich dachte zuerst das soll die Kodierung von komprimierten Daten erraten, dabei ist die Funktion dazu da, um zu testen, ob man die "simple"-Komprimierung anwenden kann. 'komplex' und 'simple' sind auch wieder Kandidaten für Konstanten. Das Schliessen der Datei sollte man nur an einer Stelle der Funktion machen, hier würde sich ein ``try``/``finally`` anbieten. Oder ab Python 2.5 die ``with``-Anweisung. Bei 2.5 braucht man noch ein ``from __future__ import with_statement`` dafür -- ab 2.6 ist ``with`` auch ohne diesen Import ein Schlüsselwort der Sprache.
`getMethod()` ist so nicht besonders robust, wenn man weitere Verfahren einbaut. Es sollte explizit der Fall behandelt werden, bei dem eine unbekannte Kodierungsinformation in der Datei steht. Das, und auch eine fehlende Kennung sollten nicht mit "speziellen" Rückgabewerten, sondern mit Ausnahmen angezeigt werden. Und auch hier sollte man die Datei nur an einem Punkt schliessen.
Der Name `setExt()` ist wieder schlecht gewählt, weil man da erwarten würde, dass diese Methode nichts zurück gibt, sondern den Zustand des Objektes verändert, auf dem sie aufgerufen wird. Aber diese "Methode" ist ja auch gar keine, sondern eine Funktion die sinnlos in eine Klasse gesteckt wurde. Die Klammern beim ``return`` sind überflüssig, und der Code hat an der Stelle auch Probleme mit Dateinamen, die mehr als einen Punkt enthalten.
Bei "Setter"-Methoden erwartet man auch, dass sie einen Wert als Argument entgegenehmen, also `setStatusQuiet(self, value)`.
Der ganze Quelltext auf Modulebene ab ``#MAIN`` sollte in einer Funktion verschwinden. So hast Du immer noch unzählige Namen im Modul, die da nicht hingehören.
Die Funktionen enthalten zum Teil redundanten Quelltext, den man herausziehen sollte.
Du solltest überlegen aus all Deinen ``while``-Schleifen, bei denen Du davor einen Schritt tust um den Namen in der Abbruchbedingung zu initialisieren und die im Schleifenkörper den *gleichen* Schritt noch einmal enthalten in "Do-While"-Schleifen umzuwandeln, also in ``while True:``-Schleifen, die im Schleifenkörper eine Abbruchbedingen mit einer ``break``-Anweisung enthalten. Das ist für solche Schleifen idiomatischerer Code. Oder das ganze so umändern, dass man eine Funktion hat, die einen Iterator über Bytewerte liefert. Vielleicht auch mit einlesen der Daten in grösseren Blöcken. Für jedes Byte einzeln `file.read()` aufzurufen ist nämlich extrem ineffizient.
Den Bildschirm löschen, hat in Kommandozeilenprogrammen nichts zu suchen. Dafür werden Dich die Anwender verfluchen, weil sie da vielleicht noch wichtige Informationen stehen hatte, die Du ihnen einfach ungefragt weglöschst. Ausserdem sind ``os.system('cls')`` und das `msvcrt`-Modul windowsspezifisch. Du schränkst damit völlig unnötig das Betriebssystem auf Windows ein.
Es gibt einen Unterschied zwischen Optionen und Argumenten. Option kommt von optional, also etwas das man weglassen kann. Wenn man eine Option nicht weglassen kann, dann ist es semantisch keine Option mehr und man sollte es auch nicht also solche behandeln. Wenn der Benutzer angeben *muss* ob komprimiert oder dekomprimiert werden soll, oder er einen Dateinamen angeben *muss*, dann sind Optionen das falsche Mittel. Also entweder ist einer der beiden Modi die Voreinstellung und es wird ein Dateiname vorgegeben oder die Standardein/ausgabe verwendet, oder Du solltest die Benutzerschnittstelle überdenken.