Seite 1 von 1

Externe Python Module im eigenen Script auslagern

Verfasst: Mittwoch 24. Juni 2009, 00:22
von cryzed
Hallo, habe meiner Meinung nach einen ganz interessanten Weg gefunden externe Python Module einfach in seinem eigenen Script auszulagern. Klar ist das nicht der optimale Weg, ich könnte auch genauso gut einfach alle Module in eine *.zip Datei packen oder einfach mit ins Verzeichnis, aber ich finde es hat seine Vorzüge wenn ich einfach eine einzige Python Datei habe die alle externen Abhängigkeiten intern auflöst und diese dann ggf. vielleicht an einen Klienten geben kann:

Code: Alles auswählen

#!/usr/bin/env python

import os
import sys
import base64
import tempfile

MODULES = "...
http://paste.pocoo.org/show/125169/

So kann man dann die Module in der "modules.py" in seinem Script verfügbar machen.

Code: Alles auswählen

#!/usr/bin/env python

from modules import *
import mechanize

def main():
    browser = mechanize.Browser()

if __name__ == "__main__":
    main()
Nach der Interpretation der dritten Zeile werden dann die Module verfügbar die im base64 string in der "modules.py" stecken und dort importiert worden sind. Klar ist natürlich auch das man die "modules.py" nicht wie hier auslagern muss sondern einfach die eigentliche Funktionalität des Scriptes mit in die "modules.py" packen kann.

PS: Ich glaube das funktioniert nur mit einer Python Version von 2.3 und höher aufgrund des sonst fehlenden "zipimporter" Modul.

Verfasst: Sonntag 28. Juni 2009, 07:37
von str1442
Du schließt die Datei nicht, die du öffnest, sondern wirfst das Dateiobjekt einfach weg. if __name__ == "__main__" könntest du noch benutzen. Die decode() Methode von Strings unterstützt base64.

Ich würde sowas nicht benutzen. Zum einen halte ich generell nicht viel davon, Komplettpakete mit allen notwendigen Abhängigkeiten zu verteilen, zum anderen gibt es genug "Homebrew" Lösungen für irgendwelche Installationsroutinen so das man sich als Anwender gar nicht mehr sicher sein kann, was da im Hintergrund alles passiert. Und Daten einfach als Strings in einem Programm abzulegen konterkariert den Sinn der Datei. Wenn du unbedingt sowas brauchst (und meine Vermutung richtig ist, daß dieser Mechanismus auf Windows Benutzer zielt), sieh dir py2exe an.

Verfasst: Freitag 3. Juli 2009, 09:36
von cryzed
str1442 hat geschrieben:Du schließt die Datei nicht, die du öffnest, sondern wirfst das Dateiobjekt einfach weg. if __name__ == "__main__" könntest du noch benutzen.
Ich bin mir ziemlich sicher das der garbage collector von Python kurz darauf das Handle schließt. Ganz abgesehen davon brauche ich es innerhalb des Programms gar nicht mehr.
str1442 hat geschrieben:Ich würde sowas nicht benutzen. Zum einen halte ich generell nicht viel davon, Komplettpakete mit allen notwendigen Abhängigkeiten zu verteilen, zum anderen gibt es genug "Homebrew" Lösungen für irgendwelche Installationsroutinen so das man sich als Anwender gar nicht mehr sicher sein kann, was da im Hintergrund alles passiert.
cryzed hat geschrieben:Klar ist das nicht der optimale Weg [...]
str1442 hat geschrieben:Und Daten einfach als Strings in einem Programm abzulegen konterkariert den Sinn der Datei.
Wieso?
str1442 hat geschrieben:Wenn du unbedingt sowas brauchst (und meine Vermutung richtig ist, daß dieser Mechanismus auf Windows Benutzer zielt), sieh dir py2exe an.
Du liegst falsch, das soll nachher unter anderem eine Technik sein um XChat Plugins cross-platform in einer einzigen Datei verteilen zu können.
Das mit der .decode() Funktion von String habe ich nicht gewusst, aber vieles was du geschrieben hast ist einfach nur Subjektiv - Ich halte es nämlich für eine sehr gute Idee, Komplettpakete mit den nötigen Abhängikeiten zu verteilen, anstatt darauf zu bestehen und zu vertrauen das der User, ob jetzt Windows/Linux/Mac/etc., auf jeden Fall all die Pakete auch installiert hat und hoffentlich auch die richtigen Versionen.

Verfasst: Freitag 3. Juli 2009, 10:54
von lunar
Der GC von CPython löscht Objekte sofort, wenn die Anzahl der Referenzen null erreicht. Das ist allerdings ein Implementierungsdetail und weder durch Dokumentation noch durch Sprachspezifikation garantiert. Jython und IronPython verwenden daher auch nicht-deterministische GC. Außerdem garantiert auch CPython den Aufruf des Destruktors nicht, wenn sich der Interpreter beendet. In diesem Fall wird die Datei nicht korrekt geschlossen, was zu Datenverlust führt, da alle Daten aus den Puffern der C-Bibliothek verfallen und nicht geschrieben werden.

Wenn es heißt, Dateiobjekte immer schließen, dann ist das durchaus ernst gemeint!

Verfasst: Freitag 3. Juli 2009, 11:01
von BlackJack
@cryzed: Du kannst Dir aber nicht sicher sein, dass der GC das Dateiobjekt zeitnah abräumt. Die Sprache gibt dafür keine Garantien. Es ist einfach unsauber sich darauf zu verlassen.

Das Mitliefern von allen Abhängigkeiten ist eher unter Windows üblich. Linuxer benutzen einfach die Paketverwaltung um Abhängigkeiten zu installieren. Für Python gäbe es da noch Eggs und `easy_install`.

Und dann geht es ja auch um diese "perverse" Form alles als kodierte Binärdaten in den Quelltext zu stecken. Man könnte schliesslich auch ein Archiv packen und das verteilen.

Verfasst: Freitag 3. Juli 2009, 13:01
von cryzed
BlackJack hat geschrieben:Man könnte schliesslich auch ein Archiv packen und das verteilen.
Das schrieb ich ja im ersten Post, aber wie gesagt ich finde es ganz gut und interessant es so zu machen.
@lunar, @BlackJack, vielen Dank für den Hinweis mit dem GC.

Verfasst: Donnerstag 16. Juli 2009, 07:26
von str1442
(Ich war länger nicht da, deswegen antworte ich erst jetzt):
Wieso?
Weil eine Datei für die Ablage von Daten jeglicher Art gedacht ist. Das ist ihr Sinn. Diese Daten in ein Programm zu stecken (welches ja eigentlich nur ein Programm sein sollte - also nur die Daten beinhalten sollte, die diese *.py Datei zu einem Python Programm macht) steht dem direkt gegenüber.
aber vieles was du geschrieben hast ist einfach nur Subjektiv
Der gesamt Teil nach dem ersten Absatz war mit Absicht subjektiv - ich habe ja geschrieben: *Ich* würde soetwas nicht benutzen. Der Rest dahinter ist meine Meinung. Du kannst soetwas gerne nutzen, wenn du es für sinnvoll hälst. Nur ich tue eben genau das nicht.